Старый 06.11.2003, 18:29   #1   
Форумец
 
Сообщений: 1,696
Регистрация: 24.11.2002
Возраст: 39

LSL вне форума Не в сети
Question c++ cout

Друг-сишник задался вопросом:

i = 1

cout << i << i++ << i

Почему на выходе 2 1 2, ведь должно 1 1 2 ?
  Ответить с цитированием
Старый 06.11.2003, 18:42   #2   
Форумец
 
Аватар для Noname
 
Сообщений: 10,697
Регистрация: 20.09.2002
Возраст: 34

Noname вне форума Не в сети
потому что так писать нельзя. Поведение кода здесь будет совершенно неопределенным. Компилятор совсем не обязан вычислять эти выражения в порядке вывода, он это может сделать как угодно. Единственное, что можно сказать, что в середине будет единица.
А потом теоретически возможны варианты:

1 1 1
1 1 2
2 1 1
2 1 2

Просто не надо писать такой код.
  Ответить с цитированием
Старый 06.11.2003, 18:58   #3   
Форумец
 
Аватар для RomanPshenichny
 
Сообщений: 334
Регистрация: 14.04.2003
Возраст: 42

RomanPshenichny вне форума Не в сети
VC 7.1 release выдает 112, а debug 212.

Неопределен порядок вычисления выражений между точками следования (sequency point). Результат может быть любым.

Этот код аналогичен:

func ( func ( func (0, i), i++ ), i);
  Ответить с цитированием
Старый 06.11.2003, 19:05   #4   
Форумец
 
Аватар для Noname
 
Сообщений: 10,697
Регистрация: 20.09.2002
Возраст: 34

Noname вне форума Не в сети
RomanPshenichny совершенно верно...
  Ответить с цитированием
Старый 07.11.2003, 14:45   #5   
Форумец
 
Сообщений: 94
Регистрация: 16.03.2003

Павел-Kikoz вне форума Не в сети
Я, конечно, не уверен.. Но разве операторы не выполняются слева - направо? Тогда результат 112 логичен..
  Ответить с цитированием
Старый 10.11.2003, 09:02   #6   
Форумец
 
Сообщений: 792
Регистрация: 09.01.2003

Unforgiven вне форума Не в сети
И даже более того:
$ g++ z.cpp -o z && ./z
211

$ g++ z.cpp -O2 -o z && ./z
112

Как видно, если добавить оптимизацию (-O2), то результат другой.

$gcc -v | grep version
gcc version 3.2.1 (ALT Linux, build 3.2.1-alt2)
  Ответить с цитированием
Старый 10.11.2003, 09:32   #7   
Форумец
 
Сообщений: 94
Регистрация: 16.03.2003

Павел-Kikoz вне форума Не в сети
Вот, блин.. И отлаживай потом такое..
В предыдущем посте имел в виду справа налево... Да, похоже, они выполняются как им приспичит
  Ответить с цитированием
Старый 10.11.2003, 10:03   #8   
Форумец
 
Сообщений: 792
Регистрация: 09.01.2003

Unforgiven вне форума Не в сети
Павел-Kikoz Чтобы не отлаживать такое, не надо такое писать. Кстати, если

cout << i << i++ << i

заменить на

printf("%d%d%d", i, i++, i)

то результат будет более предсказуемым. У меня всегда получается

2 1 1
  Ответить с цитированием
Старый 10.11.2003, 11:55   #9   
Форумец
 
Аватар для RomanPshenichny
 
Сообщений: 334
Регистрация: 14.04.2003
Возраст: 42

RomanPshenichny вне форума Не в сети
Павел-Kikoz

> Да, похоже, они выполняются как им приспичит

Может стоит выучить язык на котором пишите?
  Ответить с цитированием
Старый 10.11.2003, 19:31   #10   
Форумец
 
Сообщений: 5,001
Регистрация: 08.04.2003
Возраст: 40

zic вне форума Не в сети
Веревка достаточной длины чтобы выстрелить себе в ногу . Или как правильно писать программы на Си .
  Ответить с цитированием
Старый 10.11.2003, 21:36   #11   
Форумец
 
Сообщений: 1,696
Регистрация: 24.11.2002
Возраст: 39

LSL вне форума Не в сети
Спасибо. Друг будет доволен бедный друг...он обречён : ): )
  Ответить с цитированием
Старый 11.11.2003, 09:27   #12   
Форумец
 
Сообщений: 94
Регистрация: 16.03.2003

Павел-Kikoz вне форума Не в сети
Unforgiven
Ды я и не пишу таких конструкций, себе дороже...
Кстати, RomanPshenichny утверждает, что "этот код аналогичен
func ( func ( func (0, i), i++ ), i);"
RomanPshenichny
Язык-то стоит выучить... Только я не уверен, что его легко выучить на 100% (сколько там странц стандарт занимает?) А в неком достаточном объеме я его знаю (смею надеяться)
  Ответить с цитированием
Старый 11.11.2003, 09:31   #13   
Форумец
 
Сообщений: 5,001
Регистрация: 08.04.2003
Возраст: 40

zic вне форума Не в сети
Павел-Kikoz
Какой стандарт ?
с каких это пор реализации языков от MS соответсвуют каким то стандартам ? И уж точно не ансишным .
Может спецификация ?
  Ответить с цитированием
Старый 11.11.2003, 11:59   #14   
В'job'ываю
 
Аватар для NonSoluS
 
Сообщений: 678
Регистрация: 31.10.2003

NonSoluS вне форума Не в сети
Цитата:
cout << i << i++ << i

заменить на

printf("%d%d%d", i, i++, i)
тогда и <stdio.h> подрубай....
  Ответить с цитированием
Старый 11.11.2003, 13:28   #15   
Форумец
 
Сообщений: 792
Регистрация: 09.01.2003

Unforgiven вне форума Не в сети
DoZeR, само собой.
Только к чему ты это сказал? Тут где-нибудь приведен полный текст программы?
  Ответить с цитированием
Старый 11.11.2003, 15:52   #16   
Форумец
 
Сообщений: 94
Регистрация: 16.03.2003

Павел-Kikoz вне форума Не в сети
zic
Стандарт и спецификация использовались мной как синонимы. Ок, спецификация языка с++.
cout и оператор ++ это явно стандатрные переносимы вещи, не всякие там __property
Да и тут не только MS VC касается, как я понял...
Ну ладно, чот-то народ начал придираться к словам...
Ну не работает и не работает, черт с ним.
  Ответить с цитированием
Старый 11.11.2003, 16:23   #17   
Форумец
 
Сообщений: 5,001
Регистрация: 08.04.2003
Возраст: 40

zic вне форума Не в сети
Ессно не только MS .
НУ так речь то не о том ?
  Ответить с цитированием
Старый 11.11.2003, 21:20   #18   
Форумец
 
Аватар для RomanPshenichny
 
Сообщений: 334
Регистрация: 14.04.2003
Возраст: 42

RomanPshenichny вне форума Не в сети
Павел-Kikoz

> Кстати, RomanPshenichny утверждает, что "этот код
> аналогичен func ( func ( func (0, i), i++ ), i);"

cout << i << i++ << i, это:

( ( (cout::operator << (i) )::operator << (i++) )::operator << (i)

и для педантов:

( ( (std::basic_ostream<char,std::char_traits<char> >::operator<< (i) )::operator << (i++) )::operator << (i).

В функциональном виде код аналогичен func ( func ( func (0, i), i++ ), i). В котором тоже будет наблюдатся такое же неопределенное поведение.

Точка следования в обоих вариантах одна. Все пераметры operator << и func вычисляются до вызова самих функций. Т.е. сначала посчитали i, i++, i, а потом уже вызвали функции. Порядок вычисления i, i++, i внутри одной точки следования не определен. Что такое точка следования -- читайте в книжках по C++.

> сколько там странц стандарт занимает

~700. Но это смотря каким шрифтом ;)

zic

> с каких это пор реализации языков от MS соответсвуют
> каким то стандартам ?

С 2003 года, с VC 7.1.
Казалось бы, причем тут MS? ;)
Это стандартный undefined behaviour описанный в стандарте.
  Ответить с цитированием
Старый 12.11.2003, 00:35   #19   
Форумец
 
Сообщений: 5,001
Регистрация: 08.04.2003
Возраст: 40

zic вне форума Не в сети
RomanPshenichny
ДА я не спорю что темотаг наблюдается в любом случае .
Я просто к тому что в MS любит придумывать свои стандарты .
А не следывать общепринятым .
  Ответить с цитированием
Старый 12.11.2003, 08:34   #20   
Форумец
 
Сообщений: 792
Регистрация: 09.01.2003

Unforgiven вне форума Не в сети
RomanPshenichny, маленькое уточнение:
( ( (cout.operator << (i) ).operator << (i++) ).operator << (i)
  Ответить с цитированием
Старый 12.11.2003, 09:38   #21   
Форумец
 
Сообщений: 94
Регистрация: 16.03.2003

Павел-Kikoz вне форума Не в сети
RomanPshenichny
Блин, если бы я не знал, что операторы работают как функции, я бы вообще не полез в тему
"Порядок вычисления i, i++, i внутри одной точки следования не определен." - вот именно поэтому я и написал, что все достачно сложно.
  Ответить с цитированием
Старый 21.11.2003, 16:12   #22   
Registered User
 
Сообщений: 67
Регистрация: 08.07.2003
Возраст: 43

Fisher вне форума Не в сети
Re: c++ cout

Цитата:
Первоначальное сообщение от LSL
Друг-сишник задался вопросом:

i = 1

cout << i << i++ << i

Почему на выходе 2 1 2, ведь должно 1 1 2 ?
Ничего не должно быть, т.к. тут undefined behaviour и поэтому может быть все, что угодно, вплоть до форматирования диска.

Fisher добавил [date]1069425240[/date]:
Цитата:
Первоначальное сообщение от RomanPshenichny
Точка следования в обоих вариантах одна.[/B]

Все пераметры operator << и func вычисляются до вызова самих функций.
Все аргументы не обязаны вычисляться до вызова первой из функций.

Цитата:
Т.е. сначала посчитали i, i++, i, а потом уже вызвали функции. Порядок вычисления i, i++, i внутри одной точки следования не определен.
Дело не в том, что не определен порядок вычисления подвыражений внутри выражений, а в том, что нет гарантированных точек следования между вычислением i и i++. Undefined behaviour.
  Ответить с цитированием
Поиск в теме: 



Быстрый переход:

  Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения
BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.


Powered by vBulletin® Version 3.8.7
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd. Перевод: zCarot
Support by DrIQ & Netwind