Поведение && на языке программирования 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
Может кто-нибудь объяснить, почему я получаю этот ответ?
Ответы
Ответ 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
не тронут