И снова ++x + ++x !!!

Тема в разделе "LANGS.C", создана пользователем _DEN_, 11 май 2007.

  1. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    MSVC 8.0

    Код (Text):
    1. int plus(int a, int b)
    2. {
    3.     return a + b;
    4. }
    5.  
    6. int main()
    7. {
    8.     int x = 0;
    9.  
    10.     x = plus(++x, ++x);
    11.  
    12.     std::cout << x;
    13.  
    14.     return 0;
    15. }
    На экране "4". Должно быть "3". Сначала, корда я их просто оператором складывал, я подумал что для операторов, работающих со встроенными типами, могут быть оговорки в стандарте. Но когда то же самое оказалось для функции, то это уже бред.

    У кого что такая штука напечатает?
     
  2. green

    green New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2003
    Сообщения:
    1.217
    Адрес:
    Ukraine
    _DEN_
    Порядок вычисления аргументов ф-ций (а также большинства операторов) не определён. Так что компилятор волен выбирать наиболее оптимальный способ, исходя из предположения о независимости результата от порядка вычисления.
    Теоретически, он может для вычисления каждого аргумента запускать отдельный поток. :)
     
  3. CodeTao

    CodeTao Евгений

    Публикаций:
    0
    Регистрация:
    31 окт 2006
    Сообщения:
    177
    Адрес:
    штаты
    Я уже про такое слышал. Вроде где-то в стандарте оговаривается, что поведение компилятора не предсказуемое при использовании ин(де)крементирующих операциях в параметрах функции, то бишь это на усмотрение разработчиков компиляторов. В принципе результат правельный, если учитывать что значение аргументов вычисляется до помещения их в стек.
     
  4. Cr4sh

    Cr4sh New Member

    Публикаций:
    0
    Регистрация:
    17 апр 2006
    Сообщения:
    668
    >> Должно быть "3"
    почему? машинный код в любом случае будет сгенерён таким образом, что операции инкремента выполнятся до того, как управление получит ф-ция plus
     
  5. RedLord

    RedLord Member

    Публикаций:
    0
    Регистрация:
    23 июн 2005
    Сообщения:
    183
    Адрес:
    Ukraine
    _DEN_
    Comeau 4.3.9 выдал 3
     
  6. RedLord

    RedLord Member

    Публикаций:
    0
    Регистрация:
    23 июн 2005
    Сообщения:
    183
    Адрес:
    Ukraine
    _DEN_

    5.2.2 :

    The order of evaluation of arguments is unspecified. All side effects of argument expression evaluations
    take effect before the function is entered. The order of evaluation of the postfix expression and the argument
    expression list is unspecified.
     
  7. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    bash.org.ru :derisive:
     
  8. EvilsInterrupt

    EvilsInterrupt Постигающий азы дзена

    Публикаций:
    0
    Регистрация:
    28 окт 2003
    Сообщения:
    2.428
    Адрес:
    Russia
    n0name
    ГЫ )))
    Почему 14, я так и не понял (
    Первое ++и дает 6
    Второе ++и дает 7
    ну и 6 + 7 дает 13
    Почему 14 ?

    Глянул в дизасм:
    Код (Text):
    1. 7:        i = ++i + ++i;
    2. 0040155F   mov         eax,dword ptr [ebp-4]
    3. 00401562   add         eax,1
    4. 00401565   mov         dword ptr [ebp-4],eax
    5. 00401568   mov         ecx,dword ptr [ebp-4]
    6. 0040156B   add         ecx,1
    7. 0040156E   mov         dword ptr [ebp-4],ecx
    8. 00401571   mov         edx,dword ptr [ebp-4]
    9. 00401574   add         edx,dword ptr [ebp-4]
    10. 00401577   mov         dword ptr [ebp-4],edx
    почему такое? Этож неправильно! Почему он должен был складывать eax, ecx. Получается что ecx + ecx! MS VC++ 6.0
     
  9. Ultrin Faern

    Ultrin Faern New Member

    Публикаций:
    0
    Регистрация:
    25 июн 2006
    Сообщения:
    170
    Я бы на месте компилятора вообще упростил выражение -
    i = ++(++i)<<1 :)))
     
  10. maxdiver

    maxdiver Max

    Публикаций:
    0
    Регистрация:
    18 июл 2006
    Сообщения:
    308
    Адрес:
    Саратов
    _DEN_
    В Стандарте даже специальный пример дан:
    Код (Text):
    1. i = ++i + 1;  // the behavior is unspecified
     
  11. Mental_Mirror

    Mental_Mirror New Member

    Публикаций:
    0
    Регистрация:
    7 май 2007
    Сообщения:
    431
    maxdiver
    Дайте плиз стандарт.
     
  12. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    Ну е-мое...

    При чем тут порядок вычисления аргументов? Во-первых, я знаю что он не определен. Во-вторых, в моем примере он совершенно не влияет на результат и к сути вопроса вообще никакого отношения не имеет.

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

    plus(++i, ++i);

    Для того чтобы вызвать функцию, надо вычислить ее аргументы. Аргументы вычисляются последовательно. Т.к. в моем примере последовательность на результат не влияет, то будем считать, что они вычисляются по порядку.

    Сначала первый. plus(++i, ...); ++i дает 1. Все. Первый параметр функции вычеслен. Он равен 1 и больше меняться не будет. Готово. Идем дальше.
    Второй параметр. plus(..., ++i); i уже равно 1, поэтому ++i равно 2. Второй параметр вычеслен. Он равен 2 и меняться тоже не будет.
    Все, аргумены готовы, известны их значения, можно вызывать функцию.

    plus(1, 2);

    То, что студия считает что резутьтатом будет 4, говорит о том, что она думает, что ++i должно выполниться еще ДО того, как началось вычисление аргументов функции. На сколько я понимаю, это НЕПРАВИЛЬНО, т.к. любой оператор начинает свою работу не раньше того момента, как до него дошло управление.


    RedLord

    Согласен с Comeau.


    maxdiver

    Ты уверен что там префиксный, а не постфиксный?
     
  13. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    EvilsInterrupt

    С каких пор мы обращаемся к компиляторам по вопросам стандарта? ;)
     
  14. green

    green New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2003
    Сообщения:
    1.217
    Адрес:
    Ukraine
    _DEN_
    Стандарт не обязывает компилятор вычислять аргументы последовательно. Он может вычислять их даже одновременно.
    Процесс вычисления аргумента состоит из
    а. инкремента x
    б. передачи х в ф-цию (записи х в стек).

    В твоём случае компилятор VC8, вероятно, вычисляет так (1 - первый арг., 2 - второй арг.):
    1а, 2а, 1б, 2б.
    В результате вызывается plus(2, 2).

    А Comeau так:
    1а, 1б, 2а, 2б
    Результат: plus(1, 2).

    В данном случае это показывает, что компилятор VC8 использует больше возможностей для оптимизации, чем Comeau.

    ---
    Стандарт лишь регламентирует, что аргументы должны быть вычислены до выполнения кода ф-ции.
     
  15. maxdiver

    maxdiver Max

    Публикаций:
    0
    Регистрация:
    18 июл 2006
    Сообщения:
    308
    Адрес:
    Саратов
    _DEN_
    Уверен. Потому что я сделал копи-паст :)
    Впрочем, green уже всё объяснил. И префиксный, и постфиксный операторы могут дать побочные эффекты.
     
  16. maxdiver

    maxdiver Max

    Публикаций:
    0
    Регистрация:
    18 июл 2006
    Сообщения:
    308
    Адрес:
    Саратов
    Mental_Mirror
    К сожалению закачать никуда не могу - размер 2.4 Мб, и связь обрывается.
    Погугли - ключевые слова: " C++ International Standard 14882:2003 " (у меня такой версии).
     
  17. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    maxdiver

    Я не понимаю почему это UB.

    green

    Откуда уверенность в том, что вычисление конкретного аргумента не обязано быть атомарным?
     
  18. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    iso 9899: 1999 круче ;)
    Там тоже написано что не предусматривается поведения в таких ситуациях.
     
  19. green

    green New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2003
    Сообщения:
    1.217
    Адрес:
    Ukraine
    _DEN_
    От того, что стандарт не обязывает его быть атомарным. :)
     
  20. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    green

    Об этом сказано? :)

    Почему i = ++i + 1; - UB ? Единичка-то она и в Африке единичка.