Тонкости C/C++

Тема в разделе "LANGS.C", создана пользователем Nafanya, 5 фев 2011.

  1. Nafanya

    Nafanya Member

    Публикаций:
    0
    Регистрация:
    26 июл 2006
    Сообщения:
    581
    Rel

    Если cond true то получается строка "123", в противном случае строка "321". Так или что-то путаю?
     
  2. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.323
    да... пример как вызывать несколько функций в :? операторе...
     
  3. cppasm

    cppasm New Member

    Публикаций:
    0
    Регистрация:
    18 июл 2006
    Сообщения:
    923
    Для этого запятую вообще-то придумали.
     
  4. Nafanya

    Nafanya Member

    Публикаций:
    0
    Регистрация:
    26 июл 2006
    Сообщения:
    581
    Rel
    Интерсно, что после выполнения *b=100, а a=10 по-прежнему, хоть и b кажет на a. Хотя может так и должно быть...
    Код (Text):
    1. int main(void)
    2. {
    3. const int a=10;
    4. int* b;
    5. b=const_cast<int*>(&a);
    6. *b=100;
    7. cout<<a<<" "<<*b;
    8. getchar();
    9. getchar();
    10. return 0;
    11. }
     
  5. osox

    osox New Member

    Публикаций:
    0
    Регистрация:
    13 ноя 2009
    Сообщения:
    280
    нет не так и вообще это баг
    порядок вызова func не определен
    может быть и 123 и 321 и 231 и 132
    Код (Text):
    1. cond ? func(ptr, 1) | func(ptr, 2) | func(ptr, 3) : func(ptr, 3) | func(ptr, 2) | func(ptr, 1);
    Код (Text):
    1. (cond) ? (func(ptr, 1) , func(ptr, 2) , func(ptr, 3)) : (func(ptr, 3) , func(ptr, 2) , func(ptr, 1));
     
  6. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.323
    почему не определен, бинарные операторы выполняются слева-направо...

    использовать запятую без скобок в данном случае нельзя:
    Код (Text):
    1. int func(int t) { printf("%d ", t); return 1; }
    2.  
    3. int _tmain(int argc, _TCHAR* argv[])
    4. {
    5.     (true) ? func(1), func(2) : func(3), func(4);
    6.     return 0;
    7. }
    вывод:
    Код (Text):
    1. 1 2 4
    совершенно очевидно почему)

    скорее всего это происходит вот почему:
    Код (Text):
    1. int _tmain(int argc, _TCHAR* argv[])
    2. {
    3. 013C2160 55                   push        ebp  
    4. 013C2161 8B EC                mov         ebp,esp  
    5. 013C2163 83 EC 48             sub         esp,48h  
    6. 013C2166 53                   push        ebx  
    7. 013C2167 56                   push        esi  
    8. 013C2168 57                   push        edi  
    9.     const int x = 100;
    10. 013C2169 C7 45 FC 64 00 00 00 mov         dword ptr [x],64h  
    11.     int* y = (int*)&x;
    12. 013C2170 8D 45 FC             lea         eax,[x]  
    13. 013C2173 89 45 F8             mov         dword ptr [y],eax  
    14.     *b = 200;
    15. 013C2176 8B 45 F8             mov         eax,dword ptr [y]  
    16. 013C2179 C7 00 C8 00 00 00    mov         dword ptr [eax],0C8h  
    17.     printf("%d\n", a);
    18. 013C217F 6A 64                push        64h  
    19. 013C2181 68 5C 8C 3D 01       push        offset string "%d\n" (13D8C5Ch)  
    20. 013C2186 E8 0E F6 FF FF       call        @ILT+1940(_printf) (13C1799h)  
    21. 013C218B 83 C4 08             add         esp,8  
    22.     return 0;
    23. 013C218E 33 C0                xor         eax,eax  
    24. }
    то есть содержимое ячейки памяти изменилось, а константа спокойненько прописалась в коде (013С217F)...
     
  7. osox

    osox New Member

    Публикаций:
    0
    Регистрация:
    13 ноя 2009
    Сообщения:
    280
    Код (Text):
    1. 6.5.14 Logical OR operator
    2. Unlikethe bitwise | operator,the || operator guarantees left-to-right evaluation; if the
    3. second operand is evaluated, there is a sequence point between the evaluations of the first
    4. and second operands. If the first operand compares unequal to 0, the second operand is
    5. not evaluated.
    помимо этого операция коммутативная порядка тут вообще нет
    может сделать последнее | потом первое
     
  8. osox

    osox New Member

    Публикаций:
    0
    Регистрация:
    13 ноя 2009
    Сообщения:
    280
    рассмотрим несколько примеров
    допустим есть 4 + 5 + 8 - 4
    тоесть компилятор может считать его как
    4 - 4 + 5 + 8
    нельзя даже знать что будет первое сложение или вычитание не то что порядок вычисления операндов одной операции
    дальше если имеем
    все коммутативные например 5 + 7 + 9 + 4
    или как в вашем случае func | func | func
    порядок не определен как эффективней так и сделает
    результат не зависит от порядка
    и только если ассоциативные все например
    10 - 10 - 4
    или
    100 / 10 / 2
    то порядок слева направо
    потому что тут результат зависит от порядка
    и то в этом случае он не гарантирует сам порядок вычисления операндов
    а всего лиш то что операции по
    порядку будут вычислятся
    он может заранее вычислить значения трех операндов
    а потом для ассоциативных последовательно поделить или вычесть
    а в случае коммутативных даже этого не гарантируется
    полная свобода
     
  9. osox

    osox New Member

    Публикаций:
    0
    Регистрация:
    13 ноя 2009
    Сообщения:
    280
    примеры
    тут и перестановка коммутативных с ассоциативными и нет порядка при коммутативных и соблюдение порядка при ассоциативных + - можно заменить на * / | &
    Код (Text):
    1.     printf("%d\n", printf("a") + printf("b") + printf("c"));
    2. 00401001 8B 35 A0 20 40 00 mov         esi,dword ptr [__imp__printf (4020A0h)]
    3. 00401007 57               push        edi  
    4. 00401008 68 FC 20 40 00   push        offset string "c" (4020FCh)
    5. 0040100D FF D6            call        esi  
    6. 0040100F 8B F8            mov         edi,eax
    7. 00401011 C7 04 24 F8 20 40 00 mov         dword ptr [esp],offset string "b" (4020F8h)
    8. 00401018 FF D6            call        esi  
    9. 0040101A 03 F8            add         edi,eax
    10. 0040101C C7 04 24 F4 20 40 00 mov         dword ptr [esp],offset string "a" (4020F4h)
    11. 00401023 FF D6            call        esi  
    12. 00401025 03 C7            add         eax,edi
    13.  
    14. printf("%d\n", printf("a") - printf("b") - printf("c"));
    15.     printf("%d\n", printf("a") - printf("b") - printf("c"));
    16. 00401002 8B 35 A0 20 40 00 mov         esi,dword ptr [__imp__printf (4020A0h)]
    17. 00401008 57               push        edi  
    18. 00401009 68 F8 20 40 00   push        offset string "b" (4020F8h)
    19. 0040100E FF D6            call        esi  
    20. 00401010 8B D8            mov         ebx,eax
    21. 00401012 C7 04 24 F4 20 40 00 mov         dword ptr [esp],offset string "a" (4020F4h)
    22. 00401019 FF D6            call        esi  
    23. 0040101B 8B F8            mov         edi,eax
    24. 0040101D 2B FB            sub         edi,ebx
    25. 0040101F C7 04 24 FC 20 40 00 mov         dword ptr [esp],offset string "c" (4020FCh)
    26. 00401026 FF D6            call        esi  
    27. 00401028 2B F8            sub         edi,eax
    28.  
    29.     printf("%d\n", printf("a") + printf("b") - printf("c"));
    30. 00401002 8B 35 A0 20 40 00 mov         esi,dword ptr [__imp__printf (4020A0h)]
    31. 00401008 57               push        edi  
    32. 00401009 68 FC 20 40 00   push        offset string "c" (4020FCh)
    33. 0040100E FF D6            call        esi  
    34. 00401010 8B D8            mov         ebx,eax
    35. 00401012 C7 04 24 F4 20 40 00 mov         dword ptr [esp],offset string "a" (4020F4h)
    36. 00401019 FF D6            call        esi  
    37. 0040101B 8B F8            mov         edi,eax
    38. 0040101D 2B FB            sub         edi,ebx
    39. 0040101F C7 04 24 F8 20 40 00 mov         dword ptr [esp],offset string "b" (4020F8h)
    40. 00401026 FF D6            call        esi  
    41. 00401028 03 C7            add         eax,edi
    ни о каком порядке выполнения операций не может идти и речи если только в выражение не входят одни ассоциативные операции
    и то порядок на вычисление операндов не накладывается
    функции с побочными эффектами запрещены

    в порядке вычисления операндов можно быть уверенным только в && || , ?:
     
  10. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    Nafanya
    Rel
    В ассемблер полез правила языка проверять, ага. Происходит это потому, что отменять константность через const_cast можно только у объектов (переменных), изначально объявленных как не-const. В остальных случаях const_cast это UB.
     
  11. Nafanya

    Nafanya Member

    Публикаций:
    0
    Регистрация:
    26 июл 2006
    Сообщения:
    581
    Откопал указатель на функцию, от которого может поехать крыша:)
    Код (Text):
    1. double* (*(*(*fp)(int*,int*,int*))[])(float*,float*,float*);
    Но автор гарантирует, что программист способный его понять никогда не встретит проблем с указателями на функции в реальной жизни, т.к. на практике они всегда проще...
     
  12. Nafanya

    Nafanya Member

    Публикаций:
    0
    Регистрация:
    26 июл 2006
    Сообщения:
    581
    _DEN_
    А зачем у переменных, которые не являются константами, отменять константность? ИМХО бред...
     
  13. _DEN_

    _DEN_ DEN

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

    К счастью, C++ не зависит от твоего дилетантского мнения.

    Код (Text):
    1. void foo(int const& n)
    2. {
    3.     const_cast<int&>(n) = 10;
    4. }
    5.  
    6. int a = 20;
    7. int const b = 30;
    8.  
    9. foo(a); // good
    10.  
    11. foo(b); // bad
     
  14. Nafanya

    Nafanya Member

    Публикаций:
    0
    Регистрация:
    26 июл 2006
    Сообщения:
    581
    _DEN_
    Так ты сразу можешь присвоить переменной a значение 10. (int a = 20;//инициализировал a=10;//присвоил).
    Отменять константность для переменной величины - это как отменять взлет несуществующего самолета. Ты хоть понимаешь что ты делаешь и с какой целью?
     
  15. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.323
    [​IMG]

    можно предположить, что это - функция указателя на массив указателей на функцию... дай ссылку на этот бред...
     
  16. Nafanya

    Nafanya Member

    Публикаций:
    0
    Регистрация:
    26 июл 2006
    Сообщения:
    581
    Rel
    Ссылку не могу, из книжки это...
    Объявление указателя на функцию, принимающую 3 аргумента-указателя на int, а возвращающая указатель на массив указателей на функцию принимающую 3 аргумента-указателя на float и возвращающую указатель на double:)
    Крыша съехать может, но тут главное понять правило по которому парсятся такие выражения...
     
  17. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.323
    я пытался "по спирали" обойти выражение, но чет сложно... хотя я был близок... правило "по спирали":
    http://microsin.ru/content/view/1195/44/
     
  18. Nafanya

    Nafanya Member

    Публикаций:
    0
    Регистрация:
    26 июл 2006
    Сообщения:
    581
    Rel
    Вот еще попроще, но с подвохом:
    Код (Text):
    1. int (*fp(int))(int);
     
  19. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    Функция, принимающая int и возвращающая указатель на функцию, принимающую int и возвращающую int.

    Rel
    Какая нафик спираль? Право, лево - щёлкается на раз.
     
  20. Nafanya

    Nafanya Member

    Публикаций:
    0
    Регистрация:
    26 июл 2006
    Сообщения:
    581
    Booster
    ДА.