Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/57.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 短路逻辑或行为_C_Gcc_Clang - Fatal编程技术网

C 短路逻辑或行为

C 短路逻辑或行为,c,gcc,clang,C,Gcc,Clang,我的印象是,在C语言中,逻辑OR运算符| |是一个短路运算符,如果lhs为false,它不会计算rhs。我在比较OR'ed值时遇到了一个问题。有人能给我解释一下为什么下面的代码(在gcc 5.3上)的计算结果是真的吗?我在叮当声中也有同样的行为 #include <stdio.h> int main() { int attr = 2; if( ((attr & 2) != 2) || ((attr & 4) != 4) ) { p

我的印象是,在C语言中,逻辑OR运算符
| |
是一个短路运算符,如果lhs为false,它不会计算rhs。我在比较OR'ed值时遇到了一个问题。有人能给我解释一下为什么下面的代码(在gcc 5.3上)的计算结果是真的吗?我在叮当声中也有同样的行为

#include <stdio.h>

int main() {

    int attr = 2;

    if( ((attr & 2) != 2) || ((attr & 4) != 4) ) {
        printf("No short circuit?\n");
    };

    printf("%i %i\n",attr,(attr & 2));

};
((attr&2)!=2)|((attr&4)!=4)
计算结果为true,因为

  • attr&4==0
    (attr&4)!=4
    1
    ,因为
    attr&4
    不等于
    4
    。(N1570 6.5.9相等运算符)
  • 因为至少有一个操作数不是零,所以表达式的计算结果为
    1
    。(N1570 6.5.14逻辑或运算符)
  • 当控制表达式不为零时,
    if
    语句执行第一个子语句(N1570 6.8.4.1 if语句),您将其称为“计算为true的表达式”
  • 如果lhs为真,逻辑OR运算符将不计算rhs,因为在rhs为真或假的两种情况下,该值都为真

    如果lhs为false,逻辑AND运算符将不计算rhs,因为在rhs为true或false的两种情况下,该值都将为false

    引自:

    6.5.13逻辑与运算符

    [……]

    3如果&&运算符的两个操作数比较不等于0,则&&运算符应产生1;否则, 收益率为0。结果的类型为int

    4与按位二进制&运算符不同,&&运算符保证从左到右求值; 如果对第二个操作数求值,则两个操作数求值之间有一个序列点 第一个和第二个操作数。如果第一个操作数比较等于0,则第二个操作数 不计算操作数

    6.5.14逻辑或运算符

    [……]

    3如果| |运算符的任一操作数比较不等于0,则| |运算符应产生1;否则, 收益率为0。结果的类型为int

    4与按位|运算符不同,| |运算符保证从左到右求值;如果 计算第二个操作数时,第一个操作数的计算之间有一个序列点 和第二个操作数。如果第一个操作数比较不等于0,则第二个操作数为 未评估

    您拥有的代码:

    ((attr & 2) != 2) || ((attr & 4) != 4) )
    
    发生了什么:

  • (attr&2)
    计算结果为2。(0010和0010=0010,即2)
  • (2!=2)
    计算结果为0或false
  • 现在计算OR的右侧(如果左侧为真,则不会执行/计算右侧,即“短路”。但在本例中为假,因此计算右侧)
  • (attr&4)
    是按位and运算,例如0010和0100。其计算结果为0000或0
  • (0!=4)
    计算结果为1或true,因此执行if语句体
  • 然后执行程序的其余部分(最后一条语句),程序终止
  • 记住:

    • 是按位和
    • &&
      是布尔型和
    • |
      是按位或
    • |
      是布尔或
    这里有两种方法可以获得C中的短路行为:

    unsigned int bitwise_logical_or(unsigned int p, unsigned int q) {
       return (p | (q & ((p != 0) - 1))); 
    }
    
    unsigned int numerical_logical_or(unsigned int p, unsigned int q) {
       return p + (p == 0) * q;
    }
    
    如其他答案所述,
    |
    运算符返回true(0x01)或false(0x00)

    按位逻辑或
    的工作原理如下:


    如果对整数p和q执行按位or,则只在p为零时才有效。如果p不是零,则按位or将以不可预测的方式混合p和q。如果q可以设置为零,如果p大于零,我们将得到我们想要的结果。因此,当p为非零时,我们希望在q和零之间执行位and。诀窍是简单地测试p==0将返回(8位)0x00或0x01。我们需要它适当地返回0xff或0x00。我们通过检查p!=0,当p>0时返回0x01,当p==0时返回0x00。减去1,如果p>0,则得到0x00(false)。当p==0时,您已经有0x00(全零),无处可去,因此整数环绕(下溢),您得到0xff(全一)。

    您的印象是错误的。如果LHS为false,则尝试RHS。
    如果LHS为false,则不会评估RHS,这根本没有任何意义。这与逻辑OR应该是什么相反。对于逻辑AND,您的陈述是正确的。“逻辑OR运算符| |是一个短路运算符,如果lhs为false,则它不会计算rhs”“have a break!;-)啊,好的。。。这是有道理的。我的印象是,如果LHS是假的,它会短路,但我看到它与&&相反。谢谢你扫除了雾!我知道第二部分是真的……我原本以为如果第一部分是假的,第二部分就不会得到评估(&&behavior)。更令人困惑的C语义要存储在我的脑海中!!:)
    
    unsigned int bitwise_logical_or(unsigned int p, unsigned int q) {
       return (p | (q & ((p != 0) - 1))); 
    }
    
    unsigned int numerical_logical_or(unsigned int p, unsigned int q) {
       return p + (p == 0) * q;
    }