Кирилл Букаев | Репутация: 121(Кандидат)
20 мая 2009 в 15:41
Вопрос по операции вставки << в C++. Код:int x=5;cout << x << x++; Почему получается 6_5? Что справа начинается интерпретирование?
А в префиксной форме получается 6_6..
Аурел Спеян | Репутация: 109(Кандидат)
21 мая 2009 в 20:27
В cout (cout<<10<<20+1<<30;)сначала вычисляется значения переменных и записываются в стек.(начиная с последней переменой и заканчивая первой).Тесть в стеке будет(30 21 10) затем они выводятся в обратном порядке.(10 21 30).
В твоём случаи (int x=5;cout<<x<<x++;) будет следующее: сначала будет вычислено x++.Так как это "после" инкремент то x++ будет равно 5 .5-ка будет записана в стек.После этого x инкрементируется тоесть станет равным 6.6-ка будет записана в стек.В стеке теперь будет храниться (5 6).Затем стек будет выведен (не забываем что в обратном порядке).На консоли выведется 6 5
Если захотим поизвращаться -можем написать такой код: int x=5;cout<<x++<<x++<<x++<<x;В стек запишется (5 6 7 8) и на консоль выведется 8 7 6 5(естественно без пробелов. Пробелы для наглядности).
>>А в префиксной форме получается 6_6.. Естественно так получится! Код: int x =5;cout<<x<<++x;++х будет равно 6 и х тоже(тек как это префиксная форма и х сначала инкрементируется а потом инкрементирование значение (6) записывается в стек) потом в стек запишется х который равен 6.и стек выведется 6 6.
Удачи.
ps-Спасибо Ковалю Евгению.
То, что написано в ответах про стек, в принципе неверно, так как объект cout не может заранее знать о правом операнде крайней операции <<, чтобы поместить его в стек первым.
Чтобы убедиться в неправильности, попробуйте выполнить такую команду:
int x =5; cout<<x<<x++<<x;
В результате будет «656», хотя если бы было верным предыдущее объяснение, должно было получиться «655».
А «65» в исходном примере появляется потому, что у операции инкремента (++) приоритет выше, чем у операции сдвига (<<). Вот и вычисляется он раньше давая тем самым значение 5 и увеличивая другой x, входящий в выражение.
Аурел Спеян | Репутация: 109(Кандидат)
24 мая 2009 в 01:57
masai Вы не правы.Только что проверил
код:int x =5; cout<<x<<x++<<x;
выводит 655!
Компилятор Borland C++ (Старый добрый досовский компилятор).
Если поизвращаться:
код:int x =5; cout<<x<<x++<<x<<x++;
выведит 7665
speianaurel
Я тоже только что проверил. На новом линуксовском g++ для первого примера получилось «656», для второго — «7675». Впрочем, второй пример ещё более некорректен, там всё зависит от компилятора, т.к. порядок вычисления операдов в общем случае не оговаривается стандартом.
Не знаю как у вас, но мой компидятор при компиляции выдает (совершенно справедливое) предупреждение о возможном неопределенном поведении.
Для подтверждения своего объяснения сошлюсь на раздел 6.2.2 специального издания «Языка программирования C++» Страуструпа. Там написано, что порядок вычисления аргументов операции неопределен за исключением операций «,», «&&» и «||».
Там же, в разделе 6.2 приведен список операций с приоритетами, в котором можно видеть, что операция << иметт более низкий приоритет, чем ++. Очевидно, что в выражении (а это именно выражение)
cout<<x<<x++<<x;
нет операций кроме << и ++. Так как ++ имеет больший приоритет, она выполняется первой, в итоге получаем что-то вроде
cout<<6<<5<<6;
А это уже выводится как обычно.
Кстати, Страуструп пишет, что старым компиляторам не стоит особо доверять из-за мелких несовместимостей и несоответствий стандарту. Проверьте, если есть возможность, еще каким-нибудь компилятором.
Чтобы окончательно развеят сомнения, предлагаю найти в каталоге include из комплекта вашего компилятора файл ostream.h и убедиться, что никакого чтения справа налево нет. Есть перегруженная операция <<, которая если слева находится объект типа ostream, а справа — объект известного типа, кидает правый операнд в поток.
P.S. Рекомендую почитать о Sequence points. Например это: http://alenacpp.blogspot.com/2005/11/sequence-points.html
Аурел Спеян | Репутация: 109(Кандидат)
24 мая 2009 в 14:22
Попробовал в Dev C++
код int x=5;cout<<x<<x++;выводит 55.
а если набрать кодint x=5;cout<<x<<x++<<x++<<x++;выведит 5567
тоесть выходит что значения вычисляются слева на право по порядку, не смотря на более высокий приоритет инкремента.
Из всех этох эксперементов видно что что различные компиляторы по разному воспринимают одну и туже ситуацию.
Спасибо Вам большое за ссылку.Было интересно почитать.
В cout (cout<<10<<20+1<<30;)сначала вычисляется значения переменных и записываются в стек.(начиная с последней переменой и заканчивая первой).Тесть в стеке будет(30 21 10) затем они выводятся в обратном порядке.(10 21 30).
В твоём случаи (int x=5;cout<<x<<x++;) будет следующее: сначала будет вычислено x++.Так как это "после" инкремент то x++ будет равно 5 .5-ка будет записана в стек.После этого x инкрементируется тоесть станет равным 6.6-ка будет записана в стек.В стеке теперь будет храниться (5 6).Затем стек будет выведен (не забываем что в обратном порядке).На консоли выведется 6 5
Если захотим поизвращаться -можем написать такой код:
int x=5;cout<<x++<<x++<<x++<<x;В стек запишется (5 6 7 8) и на консоль выведется 8 7 6 5(естественно без пробелов. Пробелы для наглядности).
>>А в префиксной форме получается 6_6.. Естественно так получится! Код:
int x =5;cout<<x<<++x; ++х будет равно 6 и х тоже(тек как это префиксная форма и х сначала инкрементируется а потом инкрементирование значение (6) записывается в стек) потом в стек запишется х который равен 6.и стек выведется 6 6.
Удачи.
ps-Спасибо Ковалю Евгению.