如何在C中执行无分支条件算术运算?

vq8itlhq  于 2023-10-16  发布在  其他
关注(0)|答案(3)|浏览(97)

我有一个值int x,我想有条件地添加(例如)一个值int y,视bool c而定。我可以这样写代码:

bool c;    // C23, or stdbool.h macro for _Bool.  Converts to integer 0 or 1
int x, y;  // x could be a global or something

...

if (c)
    x += y;

没有分支我怎么写得出来?
如果x是一个没有其他线程可以引用的局部变量,编译器可能会将if转换为branchless,如果他们认为这更有效的话。(特别是在自动向量化的情况下,但也适用于标量。)但是对于全局变量,或者如果x实际上是*x加上int *,那么这不是线程安全的。编译器不能发明像*x += 0这样的写操作来写抽象机器不读或写的可能共享的对象,这可能会引入数据竞争并踩到其他线程存储的值。

4jb9z9bj

4jb9z9bj1#

一个基本的答案是生成一个无分支表达式,如果ctrue,则计算为y,否则计算为运算的恒等式(0表示加法/减法,1表示乘法/除法),然后使用该表达式。

选项一:布尔乘法

一个非常简单的解决方案是简单地将布尔值与y相乘,然后相加:

x += c*y;

选项二:逐位逻辑

从布尔值、按位和创建掩码,然后添加:

x += -c&y;

这样,如果布尔值为false,则对该值求反仍为0,并且按位和0与任何数字均为零,因此这将导致将0添加到该值。否则,对true求反将得到给予-1,它是2的补码中的全1,这将从按位AND返回给予y,将yx相加。

**注意:**本题以加法为例,但如果所讨论的运算是除法或乘法,则必须将值!c加到增广赋值的右操作数上。这是因为乘法恒等式是1而不是0。

例如

x *= -c&y+!c;
efzxgjgh

efzxgjgh2#

在某些架构上,编译器可以在不更改源代码的情况下为您完成此操作。
一个简短的例子(ARM):

#include <stdbool.h>

int foo(bool c, int x, int y)
{
    if (c)
        x += y;
    return x;
}
foo:
        mla     r0, r2, r0, r1
        bx      lr

https://godbolt.org/z/PzEedYc8P

lpwwtiir

lpwwtiir3#

c在C语言中可以是任何值(除非它的类型为bool),您需要将其规范化为01

x += (!!c) * y;

相关问题