1. C++ / Говнокод #11861

    +36

    1. 1
    printf("Aligment control: %d", sizeof(DataTransfer_T));

    Запостил: LispGovno, 02 Октября 2012

    Комментарии (18) RSS

    • Не смотря на комичность этого кода, он применяется в коммерческой констльной сетевой утилите.
      Мне интересно, кто первый сможет обнаружить в этом коде серьёзную ошибку.
      Ответить
    • > Мне интересно, кто первый сможет обнаружить в этом коде серьёзную ошибку.
      sizeof возвращает size_t, а %d принимает int. Эту?

      P.S. Alignment
      Ответить
      • Ali-g (indahouse) ment
        Ответить
      • Aliment
        Ответить
      • Да, нужно использовать модификатор z:
        z
        Specifies that a following d, i, o, u, x, or X conversion specifier applies to a
        size_t or the corresponding signed integer type argument; or that a
        following n conversion specifier applies to a pointer to a signed integer type
        corresponding to size_t argument.

        Интересно. Честно говоря не знал этого. Автору - плюс!
        Ответить
    • а sizeof разве не int?
      Ответить
      • Прочтите документацию по sizeof, пожалуйста.

        Стандарт C89, 6.5.3.4 The sizeof operator
        4. The value of the result is implementation-defined, and its type (an unsigned integer type) is size_t, defined in <stddef.h> (and other headers).
        Ответить
        • Хм. Как-то интересно получается, операция встроена в язык, а возвращаемый ей тип - определен в каком-то хэдере (пусть даже и стандартном).

          И не знаю, хорошо это или плохо, но ошибка вылезет только при портировании на тупоконечную платформу с size_t != unsigned.
          Ответить
          • Тупоконечную платформу недолго искать ;)

            Это 64-битные винда и линуха. У них int 32-битный (причем у винды еще и long 32-битный), а size_t и указатели 64-битные. Так что проблема вылезет быстро, ой как быстро...
            Ответить
            • ну как быстро
              надо еще поискать нечто, чей sizeof выдаст 4 гигабайта
              Ответить
              • > надо еще поискать нечто, чей sizeof выдаст 4 гигабайта
                Зачем? Если не туплю - поломается ABI у printf'а. Если я захочу вывести printf("%d %d", sizeof(xxx), yyy) он будет читать 2 32-битных значения. Но при вызове в стек будут запиханы 64-битное и 32-битное, и printf выдаст мусор.
                Ответить
                • если так рассуждать, то у принтф должны быть аналогичные проблемы с
                  http://ideone.com/gdQ9S
                  edit: так собственно они и есть :)
                  Ответить
                  • Они есть ;) А еще они есть у scanf'а. И тот, кто пишет scanf("%f", &d) где double d, об этом потом сильно жалеет. Вроде бы и читаются числа, но иногда совершенно дикая погрешность.

                    P.S. http://ideone.com/lZFUm
                    Ответить
                    • я вот чего не понимаю:
                      printf("%u %u\n", 'a', 'b');
                      
                      001D1000  push        62h  
                      001D1002  push        61h  
                      001D1004  push        offset string "%u %u\n" (1D20F4h) 
                      001D1009  call        dword ptr [__imp__printf (1D20A0h)]
                      выводит
                      97 98
                      хотя попросили выудить из стека два unsigned, когда там лежат два байта
                      Ответить
                      • Ну вот такое ABI у них. Все что меньше инта передается как инт. Надо посмотреть чего говорит стандарт насчет ellipsis.
                        Ответить
                        • Хотя стандарт тут ничего не скажет. Все-таки ABI задает разработчик операционки\компилятора, и для х86 там, видимо, прописано что все аргументы функции передаются выровненными на 4 байта...
                          Ответить
                • Да, точно. Но если %d один, как в исходном коде, то просто возьмется младшее DWORD.

                  Тупоконечный - я имел в виду big-endian, где взялось бы старшее двойное слово (скорей всего, равное нулю). (надеюсь, не напутал ничего)
                  Ответить
            • Ещё на платформах с сегментированной моделью памяти какая-нибудь 16 битная, типа как на контроллерах некоторых.
              Ответить

    Добавить комментарий