Подтвердить что ты не робот

Действительно ли поведение я = i++ не определено?

Возможный дубликат:
Could anyone explain these undefined behaviors (i = i++ + ++i , i = i++, etc…)

Согласно стандарту С++,

i = 3;
i = i++;

приведет к поведению undefined.

Мы используем термин "поведение undefined", если это может привести к более чем одному результату. Но здесь конечное значение i будет равно 4 независимо от порядка оценки, так разве это не следует называть "неуказанным поведением"?

4b9b3361

Ответ 1

Фраза "... окончательное значение i будет 4 независимо от того, какой порядок оценки..." неверен. Компилятор может испустить эквивалент этого:

i = 3;
int tmp = i;
++i;
i = tmp;

или это:

i = 3;
++i;
i = i - 1;

или это:

i = 3;
i = i;
++i;

Что касается определений терминов, если бы ответ был гарантирован 4, это не было бы неуказанным или undefined поведением, было бы определено поведение.

В соответствии с этим, это undefined поведение в соответствии со стандартом (Wikipedia), поэтому он даже свободен для этого:

i = 3;
system("sudo rm -rf /"); // DO NOT TRY THIS AT HOME … OR AT WORK … OR ANYWHERE.

Ответ 2

Нет, мы не используем термин "поведение undefined", когда оно может просто привести к более чем одному арифметическому результату. Когда поведение ограничено различными арифметическими результатами (или, в более общем плане, некоторым набором прогнозируемых результатов), его обычно называют неуказанным поведением.

Undefined поведение означает совершенно непредсказуемые и неограниченные последствия, такие как форматирование жесткого диска на вашем компьютере или просто сбой вашей программы. И i = i++ - поведение undefined.

Если у вас возникла идея, что i должно быть 4 в этом случае, неясно. На языке С++ нет абсолютно ничего, что позволило бы вам прийти к такому выводу.

Ответ 3

В C, а также в С++ порядок любой операции между двумя точками последовательности полностью зависит от компилятора и не может зависеть. Стандарт определяет список вещей, составляющих точки последовательности, из памяти это

  • точка с запятой после утверждения
  • оператор запятой
  • оценка всех аргументов функции перед вызовом функции
  • && и || Операнд

Поднимая страницу по wikipedia, списки более полные и описывают более подробно. Точки последовательности являются чрезвычайно важной концепцией, и если вы еще не знаете, что это значит, вы получите большую пользу, изучив ее сразу.

Ответ 4

i =, а я ++ - оба побочных эффекта, которые изменяют i.

i ++ не означает, что я увеличивается только после того, как весь оператор оценивается, просто чтобы было прочитано текущее значение i. Таким образом, назначение и приращение могут происходить в любом порядке.

Ответ 5

1. Нет, результат будет отличаться в зависимости от порядка оценки. Границы оценки между приращением и присваиванием отсутствуют, поэтому приращение может быть выполнено до или после назначения. Рассмотрим это поведение:

load i into CX
copy CX to DX
increase DX
store DX in i
store CX in i

В результате i содержит 3, а не 4.

В качестве сравнения в С# существует граница оценки между evaulation выражения и присваиванием, поэтому результат всегда будет 3.

2. Даже если точное поведение не указано, спецификация очень понятна в отношении того, что она покрывает и что она не охватывает. Поведение указано как undefined, оно не определено.

Ответ 6

Чтобы ответить на ваши вопросы:

  • Я думаю, что "поведение undefined" означает, что разработчик компилятора/языка свободен делать все, что он считает лучшим, и не может привести к нескольким результатам.
  • Потому что это не неуказанный. Он четко указал, что его поведение undefined.

Ответ 7

Не стоит печатать я = я ++, когда вы можете просто набрать я ++.

Ответ 8

Я видел такой вопрос на практическом тесте OCAJP. Декомпилятор IntelliJ IDEA превращает это

public static int iplus(){
    int i=0;
    return i=i++;
}

в это

public static int iplus() {
    int i = 0;
    byte var10000 = i;
    int var1 = i + 1;
    return var10000;
}

Создайте JAR из модуля, затем импортируйте как библиотеку и проверьте. enter image description here

Ответ 9

Этот вопрос старый, но, похоже, на него часто ссылаются, поэтому он заслуживает нового ответа в свете изменений в стандарте.

http://eel.is/c++draft/basic.exec

http://eel.is/c++draft/expr.ass

[expr.ass] В подпункте 1 поясняется "... последовательность присваивается после вычисления значения правого и левого операндов..." и "Правый операнд упорядочивается перед левым операндом". Здесь подразумевается, что побочные эффекты правого операнда упорядочиваются перед присваиванием, а это означает, что выражение не рассматривается в соответствии с пунктом [basic.exec], подразделом 10: "Если побочный эффект в ячейке памяти ([ intro.memory]) не секвенируется относительно другого побочного эффекта в той же области памяти или вычисления значения с использованием значения любого объекта в той же области памяти, и они не являются потенциально одновременными ([intro.multithread]), поведение не определено. "

Поведение определяется, как объяснено в следующем примере.