2014-02-16 2 views
-1
#include <iostream> 

int main() 
{ 
    int a = 0; 
    std::cout << a++ << ' ' << ++a << ' ' << a++ << '\n'; 
} 

Этот код дает мне этот выход 2 3 0 при компиляции C++ 11 на ideone.поведение компилятора при оценке подвыражения

Как известно, here Я знаю, что изменение значения переменной более одного раза без промежуточной точки последовательности приведет к неопределенному поведению, но поскольку C++ не оценивает выражения слева направо, а компьютеры не ведут себя случайным образом, Я хотел бы знать, как компилятор решает, какое подвыражение выбрать первый, второй и третий в приведенном выше примере.

Редактировать: Я использую Microsoft Visual Studio 2013, и вопрос был задан студентом, и я не мог объяснить, почему мы получаем эти случайные результаты.

+1

Какой компилятор? Какая версия? Какие параметры этого компилятора? Undefined не определено. – laune

+0

@rici Я не думаю, что это дубликат, потому что упомянутый вами вопрос говорит только о том, что мы получаем неопределенное поведение, но не объясняем почему. – Gaith

+1

@Gaith: Это неопределенное поведение, потому что стандарт говорит, что это неопределенное поведение. Другого возможного объяснения нет. – rici

ответ

1

Индивидуальный компилятор может не вести себя случайным образом (хотя ему разрешено с неопределенным поведением), но нет «компилятора». Различные компиляторы будут обрабатывать это выражение по-разному. Тот же самый компилятор будет обрабатывать его по-разному, если ему заданы разные параметры.

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

0

Существует грамматика для языка, и парсеры следуют структуре грамматики при разложении предложений языка в соответствии с терминалами и нетерминалами. Результат (по крайней мере концептуально) представляет собой абстрактное синтаксическое дерево, представляющее исходную программу как дерево узлов операций и операндов. До сих пор все довольно детерминировано, по крайней мере, до тех пор, пока применяются аналогичные методы анализа.

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

Наконец, оптимизация срабатывает, и теперь все ставки отключены. Алгоритм оптимизации может в пределах ограничений, определяемых кодом, сгенерированным до сих пор, принять решение о перетасовке вещей, сбросить бесполезный код, объединить дублированный код в альтернативных ветвях и т. Д.

Смежные вопросы