как оценивается x && y || z? - PullRequest
       31

как оценивается x && y || z?

6 голосов
/ 01 сентября 2011

С учетом

int x=1,y=2,z;

Не могли бы вы объяснить, почему результат для:

x && y || z 

равно 1?

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

Ответы [ 8 ]

19 голосов
/ 01 сентября 2011
x && y || z 

эквивалентно

(x && y) || z

если x=1 и y=2 тогда x&&y равно 1 && 2, что true && true, что true.

true || z 

всегда true. z даже не оценен

6 голосов
/ 01 сентября 2011

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

5 голосов
/ 01 сентября 2011

Оператор && имеет более высокий приоритет, чем оператор ||. См., Например, эта таблица приоритетов операторов , номера 13 и 14.

Ваш пример оценивается как (x && y) || z. Благодаря правилу короткого замыкания z никогда не оценивается, поскольку результат x && y уже равен true.

5 голосов
/ 01 сентября 2011
(bool)1 = true
(bool)2 = true

Uninitialized int относится к данным, которые были сохранены в памяти, где они помещаются в стек ... и редко это 0x00000000, и даже если это было, true || false = true.

4 голосов
/ 24 сентября 2011

Вы можете думать о x && y || z как эквивалентном:

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

Поскольку оба значения x и y фиксируются как ненулевые значения, первый оператор возврата всегда выполняется.

На 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 голос
/ 01 сентября 2011

Поскольку x && y оценивается как (x != 0) && (y != 0), что эквивалентно 1 && 1, получающему 1. И 1 || 0 равно 1, независимо от значения y.

0 голосов
/ 26 сентября 2011

Здесь есть 2 компонента:

  1. Старшинство
  2. Short-схема

Если это поможет вам вспомнить, с точки зрения математических операторов, || может быть заменен знаком плюс "+", который состоит из 2 столбцов, а && может быть заменен знаком "." и имеет приоритет умножения над "+": -)

В C ++ и C, когда вычисляется логическое выражение и результат может быть логически выведен из определенного термина, следующие термины не оцениваются: false && (expr2) - false, а expr2 не оценивается. правда || (expr3) - истина И expr3 не оценивается.

Надеюсь, это поможет =)

0 голосов
/ 26 сентября 2011

Оператор && имеет более высокий приоритет, чем оператор ||

...