Как вы оцениваете z = x- — == y 1;

#c #decrement #postfix-operator #equality-operator

Вопрос:

учитывая, что

 int w = 1;
int x = 6;
int y = 5;
int z = 0;
 
z = !z || !x amp;amp; !y;
printf("%dn", z);

z = x-- == y   1;
printf("%dn", z);
 

Может ли кто-нибудь объяснить, как строка ниже будет оцениваться как 1, если x-равно 5, а y 1 равно 6?

 z = x-- == y   1;
 

Комментарии:

1. x-- равно 6. --x было бы 5.

2. Вы путаете x-- с --x . В то время как оба выражения уменьшаются x на единицу, первое вычисляется по старому значению x , а второе-по новому значению x . Так что в вашем случае, x-- оценивает 6 , оставляя x значение 5 .

Ответ №1:

Выражение x-- , вычисленное до значения x перед уменьшением.

Так x-- == y 1 же, как 6 == 5 1 и то, что верно, тогда присваивается значение 1 z .

Ответ №2:

Выражение

 z = x-- == y   1
 

будет проанализирован как

 z = ((x--) == (y   1))
 

IOW, вы сравниваете результат x-- с результатом y 1 и присваиваете результат этого сравнения z .

Результатом x-- является текущее значение x ; побочным эффектом является x уменьшение. Итак, учитывая

 x == 6
y == 5
 

затем

 x--            == 6
y   1          == 6
(x-- == y   1) == 1
 

так 1 назначается z ; после этой оценки x будет равно 5 .

Обратите внимание, что C в этом случае не вызывает оценку слева направо- y 1 может быть оценена раньше x-- . Также имейте в виду, что побочный эффект -- оператора на x не обязательно должен быть применен сразу после оценки — все это может быть оценено как

 t1 <- y   1
t2 <- x
 z <- t2 == t1
 x <- x - 1
 

или

 t1 <- x
t2 <- y   1
 x <- x - 1
 z <- t1 == t2
 

или любой другой заказ. Обновление x и назначение z могут происходить в любом порядке, даже одновременно (либо чередуясь, либо параллельно).

В то время как идиоматическое С часто вызывает головокружение, это заходит слишком далеко. В качестве академического упражнения для изучения приоритета операторов и побочных эффектов это нормально (не очень хорошо), но любой, кто делал это в производственном коде, мог ожидать некоторого огорчения по этому поводу в обзоре кода. Если ничего другого, он плохо сканируется — просто добавление некоторых пар (как я сделал выше) значительно помогло бы в удобочитаемости.

Ответ №3:

Из стандарта C (6.5.2.4 Операторы постфиксного приращения и уменьшения)

2 Результатом оператора postfix является значение операнда. В качестве побочного эффекта значение объекта-операнда увеличивается (то есть к нему добавляется значение 1 соответствующего типа).

3 Оператор postfix — аналогичен оператору postfix , за исключением того, что значение операнда уменьшается (то есть из него вычитается значение 1 соответствующего типа)

Таким образом, в этом выражении утверждение

 z = x-- == y   1;
 

это может быть эквивалентно переписано следующим образом

 z = ( x-- ) == ( y   1 );
 

значение выражения постфиксного уменьшения x-- -это значение переменной x перед уменьшением. То есть значение выражения равно 6 .

Значение выражения y 1 также равно 6 , потому что значение y равно 5 .

И, наконец (стандарт C, операторы равенства 6.5.9)

3 Операторы == (равно) и != (не равно) аналогичны операторам отношений, за исключением их более низкого приоритета.108) Каждый из операторов дает 1, если указанное отношение истинно, и 0, если оно ложно. Результат имеет тип int. Для любой пары операндов верно ровно одно из соотношений

Так как значение выражения x-- равно значению выражения y 1 , то переменная z получает значение 1 .

Вы могли бы получить ожидаемый вами результат, сохранив оператор постфиксного декремента следующим образом

 z = ( x--, x == y   1 );
 

вставив оператор запятой. В этом случае после оператора запятой стоит точка последовательности, что означает, что во втором операнде оператора запятой x == y 1 x уже будет равно 5.

С другой стороны, если вы напишете, например, выражение так

 z = --x == y   1;
 

где вместо постфиксного оператора декремента используется оператор унарного декремента-тогда значение выражения-x будет равно 5 (значение оператора унарного декремента-это значение его операнда после декрементирования). В этом случае переменная z получает значение 0 , потому 5 что не равно 6 (значение выражения y 1 ).