Почему `x--> 0` не неопределенное поведение, а` x = x - `есть? - PullRequest
3 голосов
/ 07 февраля 2011

Как всем известно, этот цикл проходит через ноль:

while (x-- > 0) { /* also known as x --> 0 */
  printf("x = %d\n", x);
}

Но x = x-- дает неопределенное поведение .


Оба примера требуют некоторого возврата'значение x--, которого там нет, я думаю.Как может быть, что x-- > 0 определен, а x = x-- - нет?

Ответы [ 5 ]

19 голосов
/ 07 февраля 2011

Потому что в x = x-- вы изменяете значение x дважды без промежуточной точки последовательности.Так что порядок операций не определен.В x-- > 0 значение x изменяется один раз, и четко определено, что результатом оценки x-- будет значение x до уменьшения.

7 голосов
/ 07 февраля 2011

Я не знаю, откуда вы взяли, что «нужно какое-то« возвращаемое »значение x--, которого там нет».Во-первых, не совсем понятно, что вы имеете в виду.Во-вторых, независимо от того, что вы имеете в виду, похоже, это не имеет никакого отношения к источнику неопределенного поведения в x = x--.

x = x-- приводит к неопределенному поведению, поскольку пытается дважды изменить x безпромежуточная точка последовательности.Здесь нет необходимости в «возвращаемом значении».

Основная проблема с x = x-- заключается в том, что у него есть два побочных эффекта, которые возникают в неопределенные моменты в неопределенном порядке.Один побочный эффект вводится оператором присваивания.Еще один побочный эффект внес оператор postfix --.Оба побочных эффекта пытаются изменить одну и ту же переменную x и в целом противоречат друг другу.Вот почему поведение в таких случаях объявляется неопределенным де-юре.

Например, если исходное значение x было 5, то вашему выражению требуется, чтобы x стало как 4 (побочный эффект уменьшения), так и 5 (побочный эффект)присваивания) одновременно.Излишне говорить, что для x невозможно стать 4 и 5 одновременно.

Хотя такое прямое противоречие (например, 4 против 5) не требуется для возникновения UB.Каждый раз, когда у вас есть два побочных эффекта, попадающих в одну и ту же переменную без промежуточной точки последовательности, поведение не определено, даже если значения, которые эти побочные эффекты пытаются вставить в переменную, совпадают.

3 голосов
/ 07 августа 2011

Чтобы понять это, вам нужно иметь базовое понимание точек последовательности.См. Эту ссылку: http://en.wikipedia.org/wiki/Sequence_point

Для оператора = точка последовательности отсутствует, поэтому нет гарантии, что значение x будет изменено до его повторного присвоения x.

Когда вы проверяете условие в цикле while x-- > 0, x-- оценивается, и значение используется в оценке реляционного оператора, поэтому нет вероятности неопределенного поведения, потому что x изменяетсятолько один раз.

2 голосов
/ 07 февраля 2011

Чтобы добавить что-то к другим ответам, попробуйте прочитать эту страницу википедии о точках последовательности.

1 голос
/ 01 июля 2015

Я предлагаю прочитать https://stackoverflow.com/a/21671069/258418. Если вы сложите вместе, что = не является точкой последовательности , и компилятор может чередовать операции, если они не разделеныТочка последовательности из ответов, связанных с вами, вы видите, что следующие две последовательности были бы законными:

load i to reg
increment i
assign reg to i
=> i has previous value of i

load i to reg
assign reg to i
increment i
=> i has value of previous value of i + 1

В общем: избегайте присвоения (это включает изменение до / post ++ / -) дляодна и та же переменная дважды в одном выражении.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...