Jochen Arndt
У вас есть логическое Оценка короткого замыкания - Википедия[^] операция формы
a || b
Логический результат первого выражения
z = 0
это значение левого операнда
z
после задания. Когда это значение равно нулю, логический результат равен false. Вы можете проверить это:
int z = 0;
int a = (z = 0) ? 1 : 0;
int b = (z = 1) ? 1 : 0;
printf("%d %d\n", a, b);
Это должно печатать
0 1
со всеми компиляторами.
После того, как логический результат левого члена был вычислен, вторая операция должна быть выполнена только тогда, когда первая была истинной:
int b = (z = 0) ? 1 : 0;
if (b)
b = (z++) ? 1: 0;
Затем
z
будет по-прежнему равен нулю, потому что операция приращения не выполняется.
[EDIT2]
Вышесказанное неверно (спасибо Н. в.)!
Он должен быть сбит с курса, если
(!b)
[/EDIT2]
Таким образом, компиляторы, выполняющие всегда вторую операцию, могут не соответствовать стандарту C. Я написал "Может быть", потому что не совсем уверен в этом особом случае, когда логический результат не используется.
Вы можете проверить это таким образом (все оптимизации отключены; например,- O0 с GCC):
if (z = 0 || z++)
printf("true: %d\n", z); // Never reached
else
printf("false: %d\n", z); // Always executed
Компилятор, который печатает здесь "1", не соответствует стандарту Си.
[РЕДАКТИРОВАТЬ]
Обратите внимание также, что оптимизирующие компиляторы могут обнаружить, что результат логической операции всегда ложен, и присвоить ему ноль.
z
или даже пропустить строчку
z = 0 || z++;
потому что
z
уже был установлен на ноль в предыдущей строке.
[/РЕДАКТИРОВАТЬ]
[EDIT2]
Решение 3 указывает на проблему.
Поведение не определено, как указано в предупреждении.
Попробовать это:
int z = 0;
z = 0 || z++;
printf ("z: %d\n", z);
(z = 0) || (z++);
printf ("z: %d\n", z);
С помощью GCC он будет печатать
z: 0
z: 1
[/EDIT2]