C++ - вопрос

Тема в разделе "WASM.ZEN", создана пользователем scf, 12 ноя 2005.

  1. scf

    scf Member

    Публикаций:
    0
    Регистрация:
    12 сен 2005
    Сообщения:
    386
    Имеем код:
    Код (Text):
    1.  
    2. class C{
    3. public:
    4.     C(DWORD id): id(id) {};
    5.     __forceinline  operator DWORD&();
    6.     DWORD id;
    7. };
    8.  
    9. DWORD dw;
    10.  
    11. __forceinline C::operator DWORD &()
    12. {
    13.     dw = id;
    14.     return dw;
    15. }
    16. void main()
    17. {
    18.     C a(1);
    19.     C b(2);
    20.  
    21.     printf("%i %i", (DWORD)a, (DWORD)b);
    22. }
    23.  


    Под VC7.1 в конфигурации debug получаем на выходе 1 2

    Release - 1 1

    Вопрос: Чей это глюк и где он?
     
  2. screw

    screw New Member

    Публикаций:
    0
    Регистрация:
    12 ноя 2005
    Сообщения:
    2
    глюк в шаловливых руках. sequence points при расчёте аргументов printf нету, студия в релизе их сначала сосчитала, а потом только распечатала. Есс-но второй вызов C::operator(DWORD) похерил глобальную переменную.



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



    Итог: студия всё корректно делает. А вот автор специально этого эффекта добивался. Зачем ?
     
  3. scf

    scf Member

    Публикаций:
    0
    Регистрация:
    12 сен 2005
    Сообщения:
    386
    Можно подробнее?

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

    По замыслу, printf("%i %i", (DWORD)a, (DWORD)b);

    эквивалентно

    printf("%i %i", dw=a.id, dw=b.id);

    Что такое sequence points?
     
  4. _DEN_

    _DEN_ DEN

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



    Не надо далеко ходить.



    Достаточно:



    int i = 0;

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



    Скомпили в дебаге и релизе. Увидешь разницу.
     
  5. scf

    scf Member

    Публикаций:
    0
    Регистрация:
    12 сен 2005
    Сообщения:
    386
    debug:4410

    release:2200

    Помнится, в Сях выражения вычисляются справа налево... Кто-нибудь может объяснить этот эффект?
     
  6. vito

    vito New Member

    Публикаций:
    0
    Регистрация:
    14 ноя 2004
    Сообщения:
    177
    Хе а вот так корретно и в релизе и в дебаге.



    printf("%i", (DWORD)a);

    printf("%i", (DWORD)b);
     
  7. vito

    vito New Member

    Публикаций:
    0
    Регистрация:
    14 ноя 2004
    Сообщения:
    177
    _DEN_

    Мимо:)

    Интел все корректно скомпилил.
     
  8. scf

    scf Member

    Публикаций:
    0
    Регистрация:
    12 сен 2005
    Сообщения:
    386
    2 vito: мой случай он тоже корректно компилит? :)
     
  9. vito

    vito New Member

    Публикаций:
    0
    Регистрация:
    14 ноя 2004
    Сообщения:
    177
    ИМХО баг имеет место быть.
     
  10. screw

    screw New Member

    Публикаций:
    0
    Регистрация:
    12 ноя 2005
    Сообщения:
    2
    2vito: ерунду говоришь. Родной, ну где ты там баг увидел ?



    Приоритет определяет расстановку скобок в выражении. Что означает — какие операнды будут отданы какой функции/оператору.



    Ассоциативность действует для встроенных типов: оптимизирующий компилятор может подшаманить в выражении, чтобы, например, просуммировать все константы

    1 + x() + 2 == (1+2) + x()



    Порядок вычислений в выражении — implementation-defined, и зависит от настроек оптимизации компилятора. (Понятно, что зависимые подвыражения вычислятся позднее, чем их аргументы).



    Например, в





    f( g1(), g2(), h( g3(), g4(), t( g5() ) ) )



    порядок вызовов g1()...g5() произволен.





    x1 = g1();

    x2 = g2();



    x3 = g3();

    x4 = g4();



    y34 = h(x3,x4);



    x5 = g5();



    y5 = t(x5);



    z = f(x1,x2,x3,x4,x5);



    (найти все вариации оставляю тем, кому делать нечего).



    Это касается и операторов, как встроенных, так и перекрытых.
     
  11. green

    green New Member

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

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



    Исключение составляют лог. ф-ции(операторы) &&, ||.

    ДЛя них порядок вычисления определён.
     
  12. vito

    vito New Member

    Публикаций:
    0
    Регистрация:
    14 ноя 2004
    Сообщения:
    177
    screw

    Ну что ты так разволновался:)



    Вопрос толко один. Почему МS и Intel по разному воспринимают аналогичиный код? Причем второй корректно? ( при равнозначных опциях компилятора)

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

    Значит у Intel'а Порядок вычислений в выражении - не произволен?



    Вот недавно доделал проект и релиз перекомпилил под Intel, тот выплюнул сразу две ошибки, т.е. действительно ошибки, которые MS спокойно глотал? Гм... особенность реализации?



    З.Ы.То что автор намеренно добивался такого результата понятно. Действително принципиалных ошибок компилятора здесь нет, вопрос в различнях компиляторов. И соответственно вопрос в корректности.
     
  13. infern0

    infern0 New Member

    Публикаций:
    0
    Регистрация:
    7 окт 2003
    Сообщения:
    811
    Адрес:
    Russia


    ...главная проблема всех программ - они делают то что написано а не то что хотелось программисту...
     
  14. vito

    vito New Member

    Публикаций:
    0
    Регистрация:
    14 ноя 2004
    Сообщения:
    177
    infern0



    ...главная проблема всех программ - они делают то что написано а не то что хотелось программисту...



    Сильно сказано:))
     
  15. scf

    scf Member

    Публикаций:
    0
    Регистрация:
    12 сен 2005
    Сообщения:
    386
    и не в тему... думаю, green дал достаточно полный ответ :))
     
  16. rgo

    rgo New Member

    Публикаций:
    0
    Регистрация:
    21 мар 2005
    Сообщения:
    87
    а вот мне всё равно не до конца ясно...

    Проблема ведь в чём, как мне кажется. Что C, что C++, априори считает что произвольная функция не является pure. То есть она меняет контекст вычисления. Следовательно если есть два вызова функций в выражении, то их следует считать зависимыми, если конечно при объявлении этих функций не использовалось активно слово const. Или атрибут pure в gcc, или ещё что-нить в этом роде в vc++. А если они зависимы -- то неплохо было бы, если бы компилятор ругнулся. И на пример _DEN_'а gcc ругается, причём трижды (правда этот пример -- стандартный баг C). А на пример scf -- gcc не реагирует -- молчит собака. как я понял и vc++ и intel'овский компиляторы -- тоже.



    screw

    эта фраза про порядок вычисления... а если я напишу 'foo() + bar()' -- тоже порядок вызовов не определён? Не может быть. По-моему так (вроде я гдето читал такое, а может мне приснилось): операнды считаются слева направо (a() + b() + c()) или справа-налево (a() = b() = c()), а перестановки оптимизации ради, делаются только в случае когда компилятор _точно_ знает что это не изменит результата. Например, в твоём примере '1+x()+2'. Можно и в примере 'foo() + bar()', _если_ хотя бы одна из них объявлена как: 'int foo () const;', или компилятор достаточно продвинут, чтобы сообразить это самостоятельно.
     
  17. infern0

    infern0 New Member

    Публикаций:
    0
    Регистрация:
    7 окт 2003
    Сообщения:
    811
    Адрес:
    Russia


    если ты в том выражении напишешь ++i + ++i + i++ + i++ результат тоже будет определен. А оператор запятая не имеет жестко заданного порядка и определяется самими компилятором.
     
  18. Ustus

    Ustus New Member

    Публикаций:
    0
    Регистрация:
    8 авг 2005
    Сообщения:
    834
    Адрес:
    Харьков
    infern0

    оператор запятая имеет жестко заданый порядок вычисления подвыражений - слева направо. А запятая, разделяющая параметры функции - это не оператор и здесь порядок вычисления не определен (точнее определяется реализацией).
     
  19. _DEN_

    _DEN_ DEN

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







    Ты имеешь ввиду эта запятая:



    vector<int> v;

    v.push_back(0), v.resize(2), v.pop_back();



    ?
     
  20. Ustus

    Ustus New Member

    Публикаций:
    0
    Регистрация:
    8 авг 2005
    Сообщения:
    834
    Адрес:
    Харьков
    _DEN_

    Да, именно эта.

    Которую даже можно перегрузить, если кому-то неприятностей мало в жизни :)