С Новым годом! Форум программистов, компьютерный форум, киберфорум
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
alsav22
5428 / 4823 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
#1

Инкремент и вывод на консоль. Непонятное. - C++

11.08.2011, 02:05. Просмотров 660. Ответов 6
Метки нет (Все метки)

Объясните, пожалуйста, почему, если так:
C++
1
2
3
int i = 5; 
cout << i << "  "; 
cout << ++i << "\n";
, то на консоль выводится всё правильно: 5 6. А если расположить так:
C++
1
2
int i = 5; 
cout << i << "  " << ++i << "\n";
, то выводится: 6 6?
0
Лучшие ответы (1)
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
11.08.2011, 02:05
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Инкремент и вывод на консоль. Непонятное. (C++):

Интересный вывод, инкремент и декремент в cout - C++
Привет. Вот есть след. код: int i = 0; std::cout &lt;&lt; i &lt;&lt; &quot; &quot; &lt;&lt; ++i &lt;&lt; std::endl; неожиданный вывод, но понять можно. Но вот этот я...

Непонятный вывод: постфиксные и префиксные инкремент/декремент - C++
Под спойлером весь который можно просто скопипастить и запустить в онлайн компиляторе http://www.compileonline.com/compile_cpp11_online.php...

Реализовать вывод массива объектов типа Student на консоль (файловый ввод/вывод) - C++
Как сделать чтобы список студентов выводился на экран в конце? #include&lt;iostream&gt; #include&lt;stdio.h&gt; #include&lt;stdlib.h&gt; ...

Вывод в консоль - C++
Код без ошибок (VS не ругается при компиляции)! Но консоль не хочет выводить сообщений.. В чем может быть проблема? В консоли виден...

Вывод в консоль из dll - C++
Необходимо из dll открыть консольное окно и вывести в него нужную информацию. Уже неоднократно поднималась тема, но я так и не понял одного...

Вывод данных на консоль - C++
Здрасте. Есть такая часть кода: wstring subject = L&quot;Hello&quot;; wprintf(L&quot;Name: %s \n&quot;, subject); Почему она мне выводит на...

6
Paporotnik
383 / 227 / 7
Регистрация: 06.07.2011
Сообщений: 512
11.08.2011, 02:11 #2
ну очевидно же, что "обход" вывода идет справа налево. сначала инкрементируем, потом выводим дважды.
с инкрементом/декрементом аккуратнее надо работать. особенное если у тебя в одной строке переменная используется несколько раз.
1
Сыроежка
Заблокирован
11.08.2011, 02:33 #3
Лучший ответ Сообщение было отмечено автором темы, экспертом или модератором как ответ
Цитата Сообщение от alsav22 Посмотреть сообщение
Объясните, пожалуйста, почему, если так:
C++
1
2
3
int i = 5; 
cout << i << "  "; 
cout << ++i << "\n";
, то на консоль выводится всё правильно: 5 6. А если расположить так:
C++
1
2
int i = 5; 
cout << i << "  " << ++i << "\n";
, то выводится: 6 6?
На самом деле имеет место неопределенное поведение. На одних компиляторах может выдать, как у вас, (6, 6), а на других как (5, 6 )/ Дело в том, что оператору << соответствует вызов оператор-функции operator <<( std::cout, value ); а порядок вычисления аргументов функции не определен. То есть чтобы ыбло более понятно, то ваше выражение можно переписать, как

C++
1
operato<<r( operator<<( operator<<( operator <<( std::cout, i ), " " ), ++i ), "\n" );
В самом внешнем вызове компилятор может сначала "вычислить" выражение "\n", а затем левое выражение, которое в свою очередь представляет вызов оператора-функции. А может поступить наобороь, то есть сначала вычислить левое выражение, то есть вызвать оператор-функцию, а затем "вычислить" правое выражение "\n".

То есть порядок вычисление параметров функции стандартом не установлен, а потому поведение вашего выражения неопределено. Это равносильно вызову f( i, ++i ), то есть сначала может быть вычислено значение левого выражения, а затем правого выражения. А может быть и наоборот, то есть сначала будет вычислено правое выражение, а затем левое. Просто обычно компиляторы начинают именно с правого выражения, так как так легче заносить параметры в стек вызова в соответствии с соглашениями вызова языка С.
3
alsav22
5428 / 4823 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
11.08.2011, 03:02  [ТС] #4
Цитата Сообщение от Сыроежка Посмотреть сообщение
На самом деле имеет место неопределенное поведение. На одних компиляторах может выдать, как у вас, (6, 6), а на других как (5, 6 )/ Дело в том, что оператору << соответствует вызов оператор-функции operator <<( std::cout, value ); а порядок вычисления аргументов функции не определен. То есть чтобы ыбло более понятно, то ваше выражение можно переписать, как

C++
1
operato<<r( operator<<( operator<<( operator <<( std::cout, i ), " " ), ++i ), "\n" );
В самом внешнем вызове компилятор может сначала "вычислить" выражение "\n", а затем левое выражение, которое в свою очередь представляет вызов оператора-функции. А может поступить наобороь, то есть сначала вычислить левое выражение, то есть вызвать оператор-функцию, а затем "вычислить" правое выражение "\n".

То есть порядок вычисление параметров функции стандартом не установлен, а потому поведение вашего выражения неопределено. Это равносильно вызову f( i, ++i ), то есть сначала может быть вычислено значение левого выражения, а затем правого выражения. А может быть и наоборот, то есть сначала будет вычислено правое выражение, а затем левое. Просто обычно компиляторы начинают именно с правого выражения, так как так легче заносить параметры в стек вызова в соответствии с соглашениями вызова языка С.
Какое правило можно из этого вывести? Чего следует избегать?
0
Сыроежка
Заблокирован
11.08.2011, 03:17 #5
Следует избегать конструкций вида f( i, ++i )
1
Mr.X
Эксперт С++
3051 / 1696 / 265
Регистрация: 03.05.2010
Сообщений: 3,867
11.08.2011, 07:55 #6
Цитата Сообщение от alsav22 Посмотреть сообщение
Какое правило можно из этого вывести? Чего следует избегать?
Между двумя точками последовательности (sequence points) (если грубо, то в пределах одного выражения) нельзя несколько раз изменять одну и ту же переменную, либо считывать ее значение после модификации, так как это ведет к неопределенному поведению.
2
alsav22
5428 / 4823 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
11.08.2011, 12:01  [ТС] #7
Благодарю всех!
0
11.08.2011, 12:01
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
11.08.2011, 12:01
Привет! Вот еще темы с ответами:

Вывод круга в консоль - C++
Доброго времени суток. Подскажите как вывести круг в консоль по заданному диаметру

Вывод строки в консоль - C++
И так, вот код: #include &lt;iostream&gt; using namespace std; int main() { cout «&quot;У каждой эпохи свой язык\ n&quot;; return 0; } Вот...

Вывод дроби в консоль - C++
Есть матрица, нахожу обратную матрицу, дошел до последнего действия, нужно в конце ее разделить на детерминант. Детерминант большой...

Вывод текста на консоль в C++ - C++
парни, необходимо перевести строку printf (&quot;%5d&quot;, a); в с++. интересует как записать “%5d” в с++


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
7
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.