Кресты / Говнокод #11861 Ссылка на оригинал

0

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

Запостил: LispGovno LispGovno, (Updated )

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

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

    P.S. Alignment
    Ответить
    • Да, нужно использовать модификатор 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, пожалуйста.

      Стандарт 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 гигабайта
              Зачем? Если не туплю - поломается ABI у printf'а. Если я захочу вывести printf("%d %d", sizeof(xxx), yyy) он будет читать 2 32-битных значения. Но при вызове в стек будут запиханы 64-битное и 32-битное, и printf выдаст мусор.
              Ответить
                • Они есть 😉 А еще они есть у 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 битная, типа как на контроллерах некоторых.
            Ответить

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

Я, guest, находясь в здравом уме и твердой памяти, торжественно заявляю:

    А не использовать ли нам bbcode?


    8