gcc 或其他编译器在条件表达式中使用时是否会自动将按位 or 转换为布尔值 or?
Does gcc or other compilers auto convert bitwise or's to boolean or's when used in conditional expressions?
如果我有一个带有逻辑或运算符||
的C语句:
if (isFoo() || isBar())
blah();
如果isFoo()
返回true,编译器生成的代码将不会执行isBar()
。
位或运算符|呢?
if (isFoo() | isBar())
blah();
可能这是潦草的书写,或者如果作者要求 isBar()
和 isFoo()
因为这些函数的副作用而同时被执行,那么他们应该更清楚地表达他们的意图。或者我错了,这是一个可以接受的C/c++习语。
然而,一个体面的编译器实际上会生成一个临时变量来做isFoo()
和isBar()
的返回值的按位或ing,当优化打开?或者它会将按位或操作转换为逻辑或操作,以便允许布尔表达式的短路,以防止调用isBar()
?
编译器可以随心所欲地优化"or'ing",但是程序必须表现得好像两个函数调用实际上都发生了,并且它们可以以的顺序发生。有一次,我天真地把||
改成了|
,因为我需要两个调用都发生,但我忘记了右调用可能发生在左调用之前,而右调用取决于左调用的结果……直到有人决定尝试用pcc
而不是gcc
编译我的代码,这个bug才出现。所以我的建议是要小心这样的东西,把你的意思写清楚。
最后,请注意我说的"好像两个函数调用实际上都发生了",因为在编译器可以确定函数没有副作用的情况下,如果左边的结果是非零值,它可能会优化右边。
"然而,一个好的编译器会生成一个临时的变量对isFoo()和isBar()当优化打开?"
是的。短路不适用于位运算符。
不,这不是一个合理的编码实践。除了||
的短路和排序语义外,它执行的操作与|
不同。
||
如果其中一个操作数非零则返回1,如果两个操作数都为零则返回0。
|
给出其操作数的按位或
碰巧的是,结果的真值将是相同的(我在输入这个答案时意识到这一点)。但是考虑相应的&&
和&
操作符。:
if (isFoo() && isBar())
当且仅当两个函数都返回非零值时为真,但是下面这个:
if (isFoo() & isBar())
当且仅当位和的结果非零时为真。如果isFoo()
返回1,isBar()
返回2(结果均为真),则isFoo & isBar()
将为0,或为false。
请注意,<ctype.h>
中声明的is*()
函数只指定为true时返回非零;它们可以并且确实返回0或1以外的值。
如果你真的想避免||
的短路行为,把结果赋值给临时对象:
bool is_foo = isFoo();
bool is_bar = isBar();
if (is_foo && is_bar) ...
我们这里讲的是C语言所以我们必须有像
这样的东西typedef int BOOL;
BOOL isFoo();
BOOL isBAr();
这是因为只有c++(而不是C)有布尔类型。
现在,当我们计算isFoo() || isBar()
时,编译器知道,由于我们使用的是逻辑,或者如果isFoo()返回true,那么无论isBar()的值如何,整个语句的计算结果都将为true,因此编译器可以安全地短路' isBar() '。
然而,当我们计算isFoo() | isBar()时,我们实际上是在对两个整数进行环运算。编译器无法知道isFoo()和isBar()只能返回0或1,因此必须对两个表达式求值,因为即使isFoo()返回1,最终结果也可能是不同的(比如3)。
c++确实有一个bool
类型,如果isFoo()
和isBar()
返回bool
s,编译器真的不需要计算isBar()
。我不是c++规范方面的专家,但我认为,由于位运算符对bool
类型没有意义,因此bool
将被提升为int
并相应地求值。
- 在没有定义返回类型的函数中返回布尔值,并将结果保存在无错误的char编译中-为什么
- 变量定义到C++布尔值转换
- 如何确保在使用基于布尔值的两个方法之一调用方法时避免分支预测错误
- 重载更少,则运算符返回相反的布尔值
- 将此布尔值传递给此函数的最有效方法是什么?
- 如何设置 c++ 类的布尔值?
- 使用 MAKEWORD / MAKEWPARAM 使用布尔值而不是布尔值
- 将 10 个线程与原子布尔值同步
- 创建类似于布尔值的变量类型
- 布尔值向量的基于范围 for 循环
- 零点和布尔值之间的比较
- 简化对两个布尔值的 4 个 if/else 检查
- 无法创建带有布尔值和矢量的地图
- 对于完成布尔值设置为 true 后未停止的循环
- fstream / ifstream / ofstream 对象如何转换为布尔值
- C++:将值赋值给原始数据类型(例如布尔值)是原子操作吗?
- 为什么布尔值不能比作最后一点?
- 如何使用返回布尔值的函数?
- C++中布尔值的逻辑"or"效率
- gcc 或其他编译器在条件表达式中使用时是否会自动将按位 or 转换为布尔值 or?