我有一个值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
这样的写操作来写抽象机器不读或写的可能共享的对象,这可能会引入数据竞争并踩到其他线程存储的值。
3条答案
按热度按时间4jb9z9bj1#
一个基本的答案是生成一个无分支表达式,如果
c
是true
,则计算为y
,否则计算为运算的恒等式(0表示加法/减法,1表示乘法/除法),然后使用该表达式。选项一:布尔乘法
一个非常简单的解决方案是简单地将布尔值与
y
相乘,然后相加:选项二:逐位逻辑
从布尔值、按位和创建掩码,然后添加:
这样,如果布尔值为false,则对该值求反仍为0,并且按位和0与任何数字均为零,因此这将导致将0添加到该值。否则,对
true
求反将得到给予-1
,它是2的补码中的全1,这将从按位AND返回给予y
,将y
与x
相加。**注意:**本题以加法为例,但如果所讨论的运算是除法或乘法,则必须将值
!c
加到增广赋值的右操作数上。这是因为乘法恒等式是1而不是0。例如
efzxgjgh2#
在某些架构上,编译器可以在不更改源代码的情况下为您完成此操作。
一个简短的例子(ARM):
https://godbolt.org/z/PzEedYc8P
lpwwtiir3#
c
在C语言中可以是任何值(除非它的类型为bool
),您需要将其规范化为0
或1