x&&y||z如何求值?

6

鉴于

int x=1,y=2,z;

能否解释一下为什么以下内容的结果是:
x && y || z 

是1吗?

x && y = 1
x && y || z = 1

11
赏金的意义是什么?这个问题是否仍然没有得到令人满意的回答? - Armen Tsirunyan
回复:“赏金是干嘛用的?”——通常人们会在问题得到满意回答时提供赏金,作为对回答者的额外奖励。这是明确允许的,尽管提供赏金的人仍然需要等待一段时间才能授予它。 - Kevin Stricker
提供赏金是防止你的问题因为重复/不相关等原因而被关闭的一种非常糟糕的方式...我认为这很可能是最主要的原因。 - R.. GitHub STOP HELPING ICE
@R.. 我不这么认为,因为提问者并没有提供悬赏。 - Armen Tsirunyan
4
请停止无缘无故地在问题上发布赏金。 - Lightness Races in Orbit
显示剩余5条评论
8个回答

20
x && y || z 

等同于

(x && y) || z

如果 x=1y=2,那么 x&&y 就是 1 && 2,即 true && true,即 true

true || z 

始终为truez甚至不被评估


6

x && y || z => (x && y) || z => 1 || z => 1


5
(bool)1 = true
(bool)2 = true

未初始化的整型是指保存在内存中的数据,通常放在栈上... 它很少是 0x00000000,即使是这样,true || false = true


5

&& 运算符的优先级高于 || 运算符。可以参考,例如,此运算符优先级表格,第 13 和 14 项。

你的示例被计算为 (x && y) || z。由于短路规则,当 x && y 的结果为 true 时,z 永远不会被计算。


+1 提到短路计算。我认为这是关键所在。 - Cory Kendall

4
您可以将x && y || z看作等价于:
int func(int x, int y, int z) {
  if (x) {
    if (y) {
      return true;
    }
  }
  if (z) {
    return true;
  }
  return false;
}

由于xy都被固定为非零值,因此第一个返回语句总是被执行。

在IA32上,没有优化的情况下,x && y || z变成了:

        movl    $1, 28(%esp)        ; store 1 in x (on stack)
        movl    $2, 24(%esp)        ; store 2 in y (on stack)
        cmpl    $0, 28(%esp)        ; compare x to 0
        je      .L6                 ; if x is 0 jump to L6
        cmpl    $0, 24(%esp)        ; compare y to 0
        jne     .L7                 ; if y is 0 jump to L7
.L6:                                ; We only get to L6 if (x && y) was false
        cmpl    $0, 20(%esp)        ; compare z to 0
        je      .L8                 ; if z is 0 jump to L8
.L7:                                ; We get to this label if either (x && y) was true
                                    ; or z was true
        movl    $1, %eax            ; copy 1 into register eax, the result
        jmp     .L9                 ; jump unconditionally to L9
.L8:                                ; We only get here if both (x && y) and z are false
        movl    $0, %eax            ; copy 0 into register eax, the result
.L9:

并且func变成了:
        cmpl    $0, 8(%ebp)        ; compare first argument (x) with 0
        je      .L2                ; jump to L2 if it is
        cmpl    $0, 12(%ebp)       ; compare second argument (y) with 0
        je      .L2                ; jump to L2 if it is
        movl    $1, %eax           ; store 1 for the return value (via register eax)
        jmp     .L3                ; jump to L3 (done, return to caller)
.L2:                               ; if we hit this label both x and y were false
        cmpl    $0, 16(%ebp)       ; compare third argument (z) with 0
        je      .L4                ; if it is 0 jump to L4
        movl    $1, %eax           ; store 1 in register eax, which is the return value
        jmp     .L3                ; jump to L3 (return to caller)
.L4:                               ; if we get here x, y and z were all 0
        movl    $0, %eax           ; store 0 in eax to return false
.L3:

启用优化后,func() 看起来更像表达式(返回值只从一个地方加载,尽管它被 x86 技术所模糊),但是表达式 x && y || z 基本上消失了,因为编译器能够在编译时推断出其值。

1
因为x && y被解释为(x != 0) && (y != 0),这等同于1 && 1,结果为1。而1 || 0是1,无论y的值是多少。

0

&& 运算符的优先级高于 || 运算符。


0

这里有两个组成部分:

  1. 优先级
  2. 短路计算

如果它能帮助你记住,在数学运算符方面,|| 可以用加号 "+" 替换,它由 2 条杠组成;而 && 可以用 "." 替换,并且具有乘法的优先级大于 "+" :-)

在 C++ 和 C 中,当布尔表达式正在被评估并且结果可以从某个术语中逻辑地推断出来时,以下术语不会被评估:

false && (expr2) 是 false AND expr2 不会被评估。

true || (expr3) 是 true AND expr3 不会被评估。

希望这可以帮到你 =)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接