операции до и после увеличения переменной дают разные результаты на TC и gcc

Вот мой простой код...

#include<stdio.h>
int main()
{
int i=5;
printf("%d %d %d %d %d ",i++,i--,++i,--i,i);
return 0;
}

В gcc он выводит как «4 5 5 5 5».

но на TC он выдает как «4 5 5 4 5»

что я знаю, что в операторе printf оценка будет слева направо, если это одно выражение, но в обычном операторе оно будет слева направо.

но если printf содержит несколько выражений, то оценка будет в стеке, элементы будут помещены в стек слева направо, но выскочат справа налево, и это оправдывает вывод TC

Поправьте меня, где я не прав???


person Udit Gupta    schedule 30.12.2011    source источник
comment
@JensGustedt: На самом деле это не дубликат этого вопроса, который не имеет неопределенного поведения (хотя принятый ответ действительно охватывает эту проблему). Он должен быть помечен как дубликат одного из множества других вопросов о злоупотреблении ++.   -  person Keith Thompson    schedule 30.12.2011


Ответы (5)


C не указывает, в каком порядке должны оцениваться аргументы функции, поэтому он не определен, и компилятор может делать это по своему выбору, в том числе произвольно и случайным образом. Бьерн Страуструп прямо говорит об этом в разделе 6.2.2 третьего издания «Язык программирования C++».

Он также приводит причину:

Better code can be generated in the absence of restrictions on expression evaluation order
person Dan    schedule 30.12.2011
comment
+1 Очень приятно видеть ссылку, подтверждающую утверждение. - person Pete Wilson; 30.12.2011
comment
@PeteWilson Ссылка на книгу C ++ в ответе на вопрос C. В ответе используется undefined вместо unspecified (порядок оценки аргументов функции unspecified. Эти два слова не означают одно и то же). И в любом случае это неправильное объяснение, поскольку программа OP действительно вызывает поведение undefined, не разделяя присваивания i точками последовательности. - person Pascal Cuoq; 30.12.2011

Я думаю, что порядок, в котором оцениваются аргументы вызова функции, не указан. Как сказано в этой статье о точках последовательности:

Порядок, в котором оцениваются аргументы, не указан

person Luca Martini    schedule 30.12.2011
comment
Да, но это не вся история. Поведение не ограничивается оценкой аргументов в произвольном порядке; это действительно не определено. Вывод может быть 42, или "a suffusion or yellow", или желтым оттенком. - person Keith Thompson; 30.12.2011

Изменение объекта (в этом коде i) более одного раза между предыдущей и следующей точкой последовательности является неопределенным поведением в C. Здесь точка последовательности возникает при вызове функции после того, как все аргументы были оценены.

person ouah    schedule 30.12.2011

Два ответа на данный момент ссылаются на неопределенность оценки аргументов функции. Правильный ответ: ваша программа не определена из-за побочных эффектов одной и той же переменной, не разделенной точка последовательности.

Действительно, порядок вычисления аргументов функции не указан. Это означает, что в операторе f(g(), h()); либо g() вызывается перед h(), либо после него.

Однако неупорядоченные побочные эффекты (как в вашей программе) вызывают неопределенное поведение, в котором может произойти что угодно.

person Pascal Cuoq    schedule 30.12.2011

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

Компилятор, как определено здесь, начинает реализовывать метод стека для аргументов, передаваемых в printf, который равен «i». Он следует этим правилам:

1) Теперь он сначала выполняет предварительные приращения, поэтому, начиная с правильного нормального i, затем выполняется --i, а затем ++i, а значение i после ++i равно 5, поэтому он реализует эти значения (всплывает), поэтому вывод < сильный>_ _ 5 5 5

2) Затем он продолжается справа налево и выполняет приращение сообщения, поэтому i--, а затем i++, поэтому значение i в конце возвращается к 5, но из-за i-- оно становится 4, но показывает 5 из-за того, что это сообщение увеличивается, поэтому окончательный вывод равен 4 5 5 5 5, а окончательное значение i равно 5

Надеюсь, мне удастся развеять ваши сомнения.

TC не следует этому, поэтому придерживается нашей человеческой логики.

person SpectreWulf    schedule 25.03.2014