#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
).