简体   繁体   English

当在条件表达式中使用时,gcc或其他编译器是否会按位或自动转换为布尔值?

[英]Does gcc or other compilers auto convert bitwise or's to boolean or's when used in conditional expressions?

If I have a C statement with the logical OR operator || 如果我有一个带有逻辑OR运算符||的C语句 :

if (isFoo() || isBar())
    blah();

I know the compiler generated code will not execute isBar() if isFoo() returns true. 我知道如果isFoo()返回true,编译器生成的代码将不会执行isBar()

What about the bitwise OR operator | 那么按位OR运算符| ?

if (isFoo() | isBar())
    blah();

Likely this is sloppy writing, or if the writer requires isBar() and isFoo() to be both be executed because of those functions' side-effects, then they should express their intent more clearly. 可能这是草率的写作,或者如果作者要求 isBar() isFoo()由于这些函数的副作用而被执行,那么他们应该更清楚地表达他们的意图。 Or maybe I'm wrong and this is an acceptable C/C++ idiom. 或许我错了,这是一个可接受的C / C ++习语。

Nevertheless, will a decent compiler actually generate a temporary variable to do the bitwise or'ing of the return values of isFoo() and isBar() when optimizations are turned on? 然而,一个体面的编译器实际上会生成一个临时变量,以便在启用优化时按顺序执行isFoo()isBar()的返回值吗? Or will it instead convert the bitwise OR operation into a logical OR operation in order to allow short-circuit'ing of the boolean expression in order to prevent the calling of isBar() ? 或者它是否会将按位OR运算转换为逻辑OR运算,以便允许布尔表达式的短路,以防止调用isBar()

The compiler is free to optimize the "or'ing" however it wants, but the program must behave as if both function calls actually happen, and they could happen in either order . 编译器可以根据需要自由地优化“或”,但程序必须表现得就像两个函数调用实际发生一样,并且它们可能以任何顺序发生。 This actually bit me once when I naively changed a || 当我天真地改变一个||时,这实际上是我的一次 to | | because I needed both calls to happen, but forgot that the right-hand call could happen before the left-hand one and that the right-hand one depended on the results of the left-hand one...and the bug didn't show up until somebody decided to try compiling my code with pcc instead of gcc . 因为我需要两次调用才能发生,但是忘了右手调用可能发生在左手调用之前,而右手调用则取决于左手调用的结果......并且bug没有出现,直到有人决定尝试使用pcc而不是gcc编译我的代码。 So my advice is to be careful with stuff like this and write out what you mean clearly. 所以我的建议是要小心这样的东西,并清楚地写出你的意思。

Finally, note that I said "as if both function calls actually happen", because in the case where the compiler can determine that a function has no side effects, it might optimize out the right-hand side if the left-hand side resulted in a nonzero value. 最后,请注意我说“好像两个函数调用实际上都发生了”,因为在编译器可以确定某个函数没有副作用的情况下,如果左侧导致的话,它可能会优化右侧非零值。

"Nevertheless, will a decent compiler actually generate a temporary variable to do the bitwise or'ing of the return values of isFoo() and isBar() when optimizations are turned on?" “然而,一个体面的编译器实际上会生成一个临时变量,以便在启用优化时对isFoo()和isBar()的返回值进行按位或运算吗?”

Yes. 是。 Short circuiting does not apply to bitwise operators. 短路不适用于按位运算符。

No, this is not a reasonable coding practice. 不,这不是一个合理的编码实践。 Apart from || 除了|| 's short-circuit and ordering semantics, it performs a different operation than | 的短路和排序语义,它执行与|不同的操作 .

|| yields 1 if either operand is non-zero, 0 if both are zero. 如果任一操作数为非零,则产生1;如果两个操作数均为零,则产生0。

| yields the bitwise or of its operands. 产生按位或其操作数。

As it happens, the truth value of the result is going to be the same (I realized this as I was typing this answer). 碰巧,结果的真值将是相同的(我意识到这就像我输入这个答案)。 But consider the corresponding && vs. & operators. 但请考虑相应的&& vs. &运算符。 This: 这个:

if (isFoo() && isBar())

will be true if and only if both functions return a non-zero value, but this: 当且仅当两个函数都返回非零值时才会为true,但是:

if (isFoo() & isBar())

will be true if and only if the bitwise and of the results is non-zero. 当且仅当按位和结果为非零时才会为真。 If isFoo() returns 1 and isBar() returns 2 (both true results), then isFoo & isBar() will be 0, or false. 如果isFoo()返回1并且isBar()返回2(两个都是真实结果),则isFoo & isBar()将为0或false。

Note that the is*() functions declared in <ctype.h> are only specified to return non-zero for true; 请注意,在<ctype.h>中声明的is*()函数仅被指定为为true返回非零值; they can and do return values other than 0 or 1. 他们可以并且确实返回0或1以外的值。

If you really want to avoid the short-circuit behavior of || 如果你真的想避免||的短路行为 , assign the results to temporaries: ,将结果分配给临时工:

bool is_foo = isFoo();
bool is_bar = isBar();
if (is_foo && is_bar) ...

We are talking straight C here so we must have something like 我们在这里直接说C,所以我们必须有类似的东西

typedef int BOOL;
BOOL isFoo();
BOOL isBAr();

This is because ony C++ (and not C) has a boolean type. 这是因为ony C ++(而不是C)有一个布尔类型。

Now when we evaluate isFoo() || isBar() 现在我们评估isFoo() || isBar() isFoo() || isBar() the compiler knows that since we are using logical or if isFoo() returns true, the the whole statement will evaluate to true regardless of the value of isBar(), the compiler can therefore safely short circuit `isBar(). isFoo() || isBar()编译器知道,因为我们使用逻辑或if isFoo()返回true,所以无论isBar()的值如何,整个语句都将计算为true,因此编译器可以安全地短路`isBar()。

However when we evaluate isFoo() | 但是当我们评估isFoo()|时 isBar() we are effectively ORing two integers. isBar()我们实际上是ORing两个整数。 The compiler has no way of knowing that isFoo() and isBar() can only return 0 or 1 and therefore will have to evaluate both expressions because even if isFoo() returns 1, the final result may be something different (like 3). 编译器无法知道isFoo()和isBar()只能返回0或1,因此必须评估两个表达式,因为即使isFoo()返回1,最终结果也可能不同(如3)。

C++ does have a bool type and if isFoo() and isBar() return bool s the compiler really does not have to evalueate isBar() . C ++确实有bool类型,如果isFoo()isBar()返回bool ,编译器实际上不必重新评估isBar() I am not an expert on the C++ specification but I imagine since bitwise operators do not make sense for bool types, the bool s will be promoted to int and evaluated accordingly. 我不是在C ++规范的专家,但我想既然位运算符不用于任何意义bool类型的bool旨意晋升为int并据此进行评估。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 gcc 的 used 属性的用例是什么? - What's the usecase of gcc's used attribute? 什么&#39;条件表达式只能是布尔值,而不是整数。&#39; 意思? - What does 'Conditional expressions can be only boolean, not integral.' mean? 当auto用于数组时,为什么它被转换为指针而不是引用? - When auto is used against array, why it's converted to pointer and not reference? GCC 不同意 Clang 和 MSVC 当使用始终为真的概念来实现概念时 - GCC disagrees with Clang and MSVC when concept that's always true is used to implement a concept 为什么F#Bitwise运算符用1表示签名类型? - Why does the F# Bitwise Operator pad with 1's for signed types? 按位或运算符对 2 的补码字节有什么特殊作用吗? - Does the bitwise OR operator do anything special to a 2's complement byte? 为什么在这里按位移位将日期替换为1s而不是0? - why does bitwise shift replace date with 1s instead of 0 here? GCC的decltype(auto)不符合标准? - GCC's decltype(auto) doesn't conform to the standard? gcc的自动矢量化消息是什么意思? - What do gcc's auto-vectorization messages mean? 使GCC和其他C ++编译器非常严格 - Making GCC and Other C++ Compilers Very Strict
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM