开发者

how is x&&y||z evaluated?

开发者 https://www.devze.com 2023-04-01 00:52 出处:网络
Given int x=1,y=2,z; Could you explain why the result for: x && y || z is 1? 开发者_JAVA百科x && y = 1

Given

int x=1,y=2,z;

Could you explain why the result for:

x && y || z 

is 1?

开发者_JAVA百科x && y = 1
x && y || z = 1


x && y || z 

is equivalent to

(x && y) || z

if x=1 and y=2 then x&&y is 1 && 2 which is true && true which is true.

true || z 

is always true. z isn't even evaluated


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


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

Uninitialized int refers to data that was saved in memory, where it is placed on stack... and it rarely is 0x00000000, and even if it was, true || false = true.


The && operator has higher precedence than the || operator. See, e.g., this operators precedence table, numbers 13 and 14.

Your example evaluates as (x && y) || z. Thanks to the short circuiting rule, z is never evaluated because the result of x && y is already true.


You can think of x && y || z as equivalent to:

int func(int x, int y, int z) {
  if (x) {
    if (y) {
      return true;
    }
  }
  if (z) {
    return true;
  }
  return false;
}

Since both x and y are fixed to be non-zero values the first return statement is always hit.

On IA32, without optimisation x && y || z becomes:

        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:

And func becomes:

        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:

With optimizations enabled func() looks even more like the expression (the return value only gets loaded from one place, although it's obscured by x86-isms), but the expression x && y || z basically disappears since the compiler is able to deduce its value at compile time.


Because x && y is evaluated as (x != 0) && (y != 0), which is equivalent with 1 && 1 resulting 1. And 1 || 0 is 1, no matter what y value is.


The && operator has higher precedence than the || operator


There are 2 components here:

  1. Precedence
  2. Short-circuitry

If it helps you remember, in terms of mathematical operators, || can be replaced with the plus sign "+", which consists of 2 bars and as && can be replaced with a "." and has the multiplication's precedence over the "+" :-)

In C++ and C, when a boolean expression is being evaluated and the result can logically be inferred from a certain term, the following terms do not get evaluated: false && (expr2) is false AND expr2 does not get evaluated. true || (expr3) is true AND expr3 does not get evaluated.

I hope this helps =)

0

精彩评论

暂无评论...
验证码 换一张
取 消