Найти:
Закрытый вопрос
3 хороший вопрос

Вопрос по операции вставки << в C++. Код:int x=5;cout << x << x++; Почему получается 6_5?

Что справа начинается интерпретирование? А в префиксной форме получается 6_6..

Спросил: KIBSOFT 3 года назад | Предложить дружбу | Добавить в эксперты

Ответов: 5 | Просмотров: 1778 | Пожаловаться на вопрос

Ответы
2 AD AD

Попробовал в Dev C++

код
int x=5;
cout<<x<<x++;
выводит 55.

а если набрать
код
int x=5;
cout<<x<<x++<<x++<<x++;
выведит 5567

тоесть выходит что значения вычисляются слева на право по порядку, не смотря на более высокий приоритет инкремента.

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

Спасибо Вам большое за ссылку.Было интересно почитать.

Ответил: speianaurel 2 года, 12 месяцев назад | Предложить дружбу | Добавить в эксперты

Пожаловаться на ответ
1 AD AD

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


speianaurel

Я тоже только что проверил. На новом линуксовском g++ для первого примера получилось «656», для второго — «7675». Впрочем, второй пример некорректен, там всё зависит от компилятора, т.к. порядок вычисления операдов в общем случае не оговаривается стандартом.

Для подтверждения своего объяснения сошлюсь на раздел 6.2.2 специального издания «Языка программирования C++» Страуструпа. Там написано, что порядок вычисления аргументов операции неопределен за исключением операций «,», «&&» и «||».

Там же, в разделе 6.2 приведен список операций с приоритетами, в котором можно видеть, что операция << иметт более низкий приоритет, чем ++. Очевидно, что в выражении (а это именно выражение)

cout<<x<<x++<<x;

нет операций кроме << и ++. Так как ++ имеет больший приоритет, она выполняется первой, в итоге получаем что-то вроде

cout<<6<<5<<6;

А это уже выводится как обычно.

Кстати, Страуструп пишет, что старым компиляторам не стоит особо доверять из-за мелких несовместимостей и несоответствий стандарту. Проверьте, если есть возможность, еще каким-нибудь компилятором.

Чтобы окончательно развеят сомнения, предлагаю найти в каталоге include из комплекта вашего компилятора файл ostream.h и убедиться, что никакого чтения справа налево нет. Есть перегруженная операция <<, которая если слева находится объект типа ostream, а справа — объект известного типа, кидает правый операнд в поток.

Ответил: masai 2 года, 12 месяцев назад | Предложить дружбу | Добавить в эксперты

Пожаловаться на ответ
0 AD AD

masai Вы не правы.Только что проверил

код:
int x =5; cout<<x<<x++<<x;

выводит 655!

Компилятор Borland C++ (Старый добрый досовский компилятор).

 

Если поизвращаться:

код:
int x =5; cout<<x<<x++<<x<<x++;

выведит 7665

Ответил: speianaurel 2 года, 12 месяцев назад | Предложить дружбу | Добавить в эксперты

Пожаловаться на ответ
0 AD AD

То, что написано в ответах про стек, в принципе неверно, так как объект cout не может заранее знать о правом операнде крайней операции <<, чтобы поместить его в стек первым.

Чтобы убедиться в неправильности, попробуйте выполнить такую команду:

int x =5; cout<<x<<x++<<x;

В результате будет «656», хотя если бы было верным предыдущее объяснение, должно было получиться «655».

А «65» в исходном примере появляется потому, что у операции инкремента (++) приоритет выше, чем у операции сдвига (<<). Вот и вычисляется он раньше давая тем самым значение 5 и увеличивая другой x, входящий в выражение.

Ответил: masai 2 года, 12 месяцев назад | Предложить дружбу | Добавить в эксперты

Пожаловаться на ответ
2 AD AD

В 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-Спасибо Ковалю Евгению.


 

<!-- /* Font Definitions */ @font-face {font-family:"Cambria Math"; panose-1:2 4 5 3 5 4 6 3 2 4; mso-font-charset:1; mso-generic-font-family:roman; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:0 0 0 0 0 0;} @font-face {font-family:Calibri; panose-1:2 15 5 2 2 2 4 3 2 4; mso-font-charset:204; mso-generic-font-family:swiss; mso-font-pitch:variable; mso-font-signature:-1610611985 1073750139 0 0 159 0;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-unhide:no; mso-style-qformat:yes; mso-style-parent:""; margin-top:0cm; margin-right:0cm; margin-bottom:10.0pt; margin-left:0cm; line-height:115%; mso-pagination:widow-orphan; font-size:11.0pt; font-family:"Calibri","sans-serif"; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi; mso-fareast-language:EN-US;} p {mso-style-noshow:yes; mso-style-priority:99; mso-margin-top-alt:auto; margin-right:0cm; mso-margin-bottom-alt:auto; margin-left:0cm; mso-pagination:widow-orphan; font-size:12.0pt; font-family:"Times New Roman","serif"; mso-fareast-font-family:"Times New Roman";} .MsoChpDefault {mso-style-type:export-only; mso-default-props:yes; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi; mso-fareast-language:EN-US;} .MsoPapDefault {mso-style-type:export-only; margin-bottom:10.0pt; line-height:115%;} @page Section1 {size:595.3pt 841.9pt; margin:2.0cm 42.5pt 2.0cm 3.0cm; mso-header-margin:35.4pt; mso-footer-margin:35.4pt; mso-paper-source:0;} div.Section1 {page:Section1;} -->

В 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-Спасибо Ковалю Евгению.

 

 

 

Ответил: speianaurel 3 года назад | Предложить дружбу | Добавить в эксперты

Пожаловаться на ответ
Темы
Сообщества
Теги
.NET 1C 3D Active Directory C C#.NET C++ C++ Builder Delphi DreamSpark ERP Ethernet EXCEL firefox HTML HTML@ intuit.ru java JavaScript Linux Mac OS Microsoft Vista Microsoft Windows Microsoft Windows XP Pro Microsoft XP OpenOffice.org Pascal PHP service desk shell SQL unix web Wi-Fi Word Word 2007: полное рукодовство WWW администрирование алгоритм алгоритмы английский язык анимация аппаратура архитектура ЭВМ архитектурное моделирование базы данных безопасность беспроводные технологии веб-дизайн верстка видео Видео курс видеокурсы вирусы Вопрос администрации сайта второе высшее высшее образование графика графические форматы диплом дипломы дистанционное обучение документооборот дополнительное образование естественные языки запуск программ игры интелект интеллект интернет интерфейсы интуит информатика исследования история кадры кибернетика книги командная строка компании компиляторы компоненты компьютерные сети консультанты конфиденциальность корпоративные системы криптография крэкинг курсы Локалные сети Локальная версия маршрутизация математика машииное обучение машинное обучение начинающий программист нейронные сети низкоуровневое ПО новейшие разработки новые учебные программы ноутбуки образование обучение объектно-ориентированное программирование объявления оплата оплата сертификата офис память печать пиратство поиск работы получение сертификата предложение предложения Принтеры программирование программное обеспечение проектирование работа сайта разное разработка приложение регистрация реляционные решение робот робототехника сайт сертификат сертификация сетевые операционные системы системы программирования спам текстовые редакторы текстуры телекоммуникационные сети телефония теория теория приближений трояны управление контентом учебная программа учебники учебные курсы учебные программы форматы данных цвета человеко-машинное взаимодействие электронные таблицы электронные учебники Эффективность Эффективность ИТ ядро языки программирования
Вопросы Темы Теги Сообщества Рейтинги Обратная связь Помощь © 2012, Интернет-Университет Информационных Технологий
Проект Издательства "Открытые Системы".
Партнеры: РМ Телеком, KRAFTWAY COMPUTERS.
Rambler's Top100