Подтвердить что ты не робот

Поведение && на языке программирования C

Я начинаю на языке программирования C, недавно я прочитал о логическом операторе AND &&.

Я также знаю, что на языке программирования C все ненулевые значения рассматриваются как TRUE.

NON-ZERO && NON-ZERO = 1  
NON-ZERO && ZERO = 0  
ZERO && NON-ZERO = 0
ZERO && ZERO = 0  

Но когда я имею дело со следующей программой, я не ожидаю ответа.

int main(){  
  int x, y, z;  
  x = y = z = -1;  
  y = ++x && ++y && ++z;  
  printf("x = %d, y = %d, z = %d, x, y, z);  
  return 0;  
} 

Я ожидаю

x = 0, y = 0, z = 0 

но ответ

x = 0, y = 0, z = -1

Может кто-нибудь объяснить, почему я получаю этот ответ?

4b9b3361

Ответ 1

Из-за Оценка короткого замыкания, когда x 0, y и z действительно не нужно оценивать, так как 0 && ANYTHING 0.

Как только x увеличивается на 0, результат равен 0, а то, что получает y.

z остается неизменным (-1).


 x  | y  |  z 
----+----+-----
 -1 | -1 | -1   //x = y = z = -1;  
  0 | -1 | -1   //++x && ... Now the whole expression is evaluated to 0
  0 |  0 | -1   //y = ++x && ++y && ++z;

Ответ 2

Я могу только подумать, что && оценивается в коротком замыкании: данный A && B, если A оценивает false, то B не оценивается.

Итак:

X становится 0. && ++y && ++z не оценивается, так как X/0/false && ...

y=0 как назначено из y = x/0/false

z остается неизменным, так как ++z не выполняется.

Ответ 3

Случается, что ++y и ++z никогда не оцениваются, потому что первая часть уже обеспечивает то, что будет новым значением y.

Первая часть вашего оператора ++x && ..., которая эквивалентна 0 && ..., и мы уже знаем, что y будет 0 в конце, так что остальная часть инструкции не будет выполнена.

если вы это сделали:

int main(){  
  int x,y,z,tmp;  
  x = y = z = -1;  
  tmp = ++x && ++y && ++z;  
  printf("x = %d, y = %d, z = %d, tmp = %d", x,y,z, tmp);  
  return 0;  
} 

Вы получите x = 0, y = -1, z = -1, tmp = 0

Левая оценка гарантируется в стандарте C99. Вы можете найти его в разделе 6.5.13 Logical AND operator

В отличие от побитового двоичного кода и оператора, && оператор гарантирует оценку слева направо; после оценки первого операнда есть точка последовательности. Если первый операнд сравнивается с 0, второй операнд не оценивается.

Вы можете найти более подробную информацию о том, что является точкой последовательности на Wikipedia или в Приложении C стандарта C99

Ответ 4

Для полноты (свалка мозга):

Термин, стоящий за этим колдовством, называется short circuiting. Переходите через свой код, а затем кратко расскажите, почему это происходит. Глядя на:

int main( void ) {  
  int x, y, z;
  x = y = z = -1;
  y = ++x && ++y && ++z;

  printf( "x = %d, y = %d, z = %d, x, y, z );

  return 0;  
}

... мы начинаем разбить его по строкам. Первая строка:

int x, y, z;

... объявляет три целых числа, x, y и z. Они инициализируются значениями мусора в фрейме стека, потому что нет инициализации (оператор присваивания). Эта строка не имеет значения, теперь посмотрим на следующую:

 x = y = z = -1;

... мы видим, что мы выполняем несколько назначений в одной строке. Напомним, что оператор присваивания будет мутировать идентификатор слева от оператора присваивания (используя значение справа от оператора присваивания) и вернуть значение x. Это называется перегрузкой назначения. Но опять же, это не имеет значения - единственное, что нужно реализовать, - это x, y и z теперь все -1. Давайте посмотрим на следующую строку:

 y = ++x && ++y && ++z;

... Волшебство Йода говорит. Позвольте добавить скобки, чтобы сделать более очевидным, какой шаг оценивается первым:

 y = ( ( ++x ) && ++y && ++z );

... теперь, глядя на внутреннюю скобку, мы видим, что это приращение префикса x, что означает, что мы увеличим значение x, а затем вернем его. Заметим, что x изначально -1, и теперь он равен 0 после приращения. Это будет разрешено следующим образом:

 y = ( 0 && ++y && ++z );

... теперь важно отметить, что глядя на наши таблицы истинности:

A | B | A && B
--------------
T | T |   T
T | F |   F
F | T |   F
F | F |   F

... для логического оператора AND мы видим, что оба F (AND) T, T (AND) F равны F. Компилятор реализует это и короткие замыкания, когда он оценивает конъюнкцию (AND), где a Значение false - умный метод оптимизации. Затем он решит присвоить y значение 0 (что является ложным). Напомним, что в C любое ненулевое значение true, только 0 равно false. Строка будет выглядеть следующим образом:

 y = 0;

... теперь смотрим на следующую строку:

 printf( "x = %d, y = %d, z = %d, x, y, z );

... теперь вам должно быть очевидно, что он выведет x = 0, y = 0, z = -1.

Ответ 5

Оператор

&& оценивается попарно, поэтому я предполагаю, что C оценивает

((++x && ++y) && ++z)

теперь ++x будет возвращать ноль, поэтому первый && будет терпеть неудачу, как и второй, без необходимости оценивать ++y или ++z.

y = 0, так как это результат выражения.

z не тронут