Он не определен, потому что он изменяется xдважды между точками последовательности. Стандарт говорит, что он не определен, поэтому он не определен.
Это много я знаю.
Но почему?
Я понимаю, что запрет этого позволяет компиляторам оптимизировать лучше. Это могло иметь смысл, когда C был изобретен, но теперь кажется слабым аргументом.
Если бы мы сегодня заново изобрели C, сделаем ли мы это так или лучше?
Или, может быть, есть более глубокая проблема, которая затрудняет определение согласованных правил для таких выражений, поэтому лучше их запретить?
Итак, предположим, что мы должны были изобрести C сегодня. Я хотел бы предложить простые правила для выражений, таких как x=x++, которые, как мне кажется, работают лучше, чем существующие правила.
Я хотел бы узнать ваше мнение о предлагаемых правилах по сравнению с существующими или другими предложениями.
Предлагаемые правила:
- Между точками последовательности порядок оценки не указан.
- Побочные эффекты имеют место немедленно.
Там нет неопределенного поведения. Выражения оцениваются в ту или иную величину, но, конечно, не отформатируют ваш жесткий диск (странно, я никогда не видел реализацию, где x=x++форматирует жесткий диск).
Примеры выражений
x=x++- Четко определено, не меняетсяx.
Сначалаxувеличивается (сразу послеx++оценки), затем сохраняется его старое значениеx.x++ + ++x- Увеличивает вxдва раза, оценивает до2*x+2.
Хотя любая из сторон может быть оценена первой, результатом будет либоx + (x+2)(левая сторона первой), либо(x+1) + (x+1)(правая сторона первой).x = x + (x=3)- Не указано,xустановлено либо либо,x+3либо6.
Если правая сторона оценивается первой, этоx+3. Также возможно, чтоx=3оценивается первым, так и есть3+3. В любом случаеx=3присвоение происходит сразу послеx=3оценки, поэтому сохраненное значение перезаписывается другим назначением.x+=(x=3)- Хорошо определено, устанавливаетсяxв 6.
Вы можете утверждать, что это просто сокращение для выражения выше.
Но я бы сказал, что это+=должно быть выполнено послеx=3, а не в двух частях (чтениеx, оценкаx=3, добавление и сохранение нового значения).
В чем преимущество?
Некоторые комментарии подняли этот хороший момент.
Я, конечно, не думаю, что такие выражения, как x=x++следует использовать в любом нормальном коде.
На самом деле, я гораздо более строг, чем это - я думаю, что единственное хорошее использование для x++в x++;одиночку.
Тем не менее, я думаю, что языковые правила должны быть максимально простыми. В противном случае программисты просто не понимают их. правило, запрещающее изменение переменной дважды между точками последовательности, безусловно, является правилом, которое большинство программистов не понимают.
Основное правило таково:
если A допустимо, а B допустимо и они правильно объединены, результат действителен.
xявляется допустимым L-значением, x++является допустимым выражением и =является допустимым способом объединения L-значения и выражения, так почему же x=x++это не законно?
Стандарт C делает здесь исключение, и это исключение усложняет правила. Вы можете поискать на stackoverflow.com и посмотреть, насколько это исключение смущает людей.
Вот я и говорю - избавьтесь от этой путаницы.
=== Сводка ответов ===
Зачем это делать?
Я попытался объяснить в разделе выше - я хочу, чтобы правила C были простыми.Потенциал для оптимизации:
это отнимает некоторую свободу у компилятора, но я не увидел ничего, что убедило бы меня в том, что это может быть важно.
Большинство оптимизаций еще можно сделать. Например,a=3;b=5;могут быть переупорядочены, даже если стандарт определяет порядок. Выражения, такие как,a=b[i++]все еще могут быть оптимизированы аналогичным образом.Вы не можете изменить существующий стандарт.
Я признаю, я не могу. Я никогда не думал, что смогу пойти дальше и изменить стандарты и компиляторы. Я только хотел подумать, если бы все могло быть сделано иначе.
xсебе, и если вы хотите увеличить,xвы можете просто сказатьx++;- нет необходимости в присваивании. Я бы сказал, что это не следует определять только потому, что трудно вспомнить, что должно было случиться.