понедельник, 20 февраля 2012 г.

C99: Форматирование целых чисел

Проблема возникла, когда мне понадобилось собирать одно и то же приложение под разные платформы под 64- и 32 битные. Использование форматного вывода не хотело работать без предупреждений об ошибках. Как правильно форматировать вывод 64 битного числа или указателя?
Изыскания в этом вопросе выявили множество макросов в определении <inttypes.h> направленных как раз на решение этой проблемы.
вместо
printf("%016llX\n", w64);
следует писать
printf("%016" PRIX64 "\n", w64);
Таких макросов там много и для функции printf и для scanf
например: PRIu64 или PRIx8, под каждый тип вида uint32_t есть свой макрос

5 комментариев:

  1. %lld - 64-битное
    %p - пойнтер (любой)
    %td - ptrdiff_t (разница между пойнтерами)

    Как я понимаю, для intptr_t тоже можно использовать %td

    ОтветитьУдалить
  2. все почти так как ты говоришь, кроме одного: под виндой win32 собирая приложение с макросом ошибок нет, а без макроса когда я использую %llX применительно к uint64_t получаю строгое предупреждение о несоответствии типов. Я конечно поверю, что компилятор макросы не проверяет вовсе, только неделимые строчки. Но именно этот выход меня успокоил. Кстати, с %llX вывод такой же как и с PRIX64, разница только в ошибках. Я по традиции собираю приложения только в режиме Warning==Error

    ОтветитьУдалить
  3. Кстати перед этим также мучился с хранением целых чисел в указателях. Тоже может отличаться вывод для m64 и m32. Написал интересную реализацию кварков, в них в режиме m64 блоки больше чем в режиме m32, а код одинаковый без единого дефайна. А перед этим была схожая проблема при переносе кода между виндой и армом (между разными платформами) тоже по разному воспринимались форматы целых чисел. Так что думаю использование макросов могло бы вылечить некоторую несовместимость.

    ОтветитьУдалить
  4. Под Mingw32 PRIx64 это "%I64x". Под Linux x86, это или "%llx" или "%lx". Вот и разница.

    ОтветитьУдалить
  5. Вся эта бодяга вылезла еще раз. Теперь не работают все мои PRIx64, потому что GCC 5.2+ подстраивается под С11. В программах 2012 года, я переписываю на и заменяю, PRIx64 на %llx. Внимательно читаю спецификацию С11. См IEEE Std 1003.1, 2013 Edition. Еще сталкивался, что компилятор не понимает %hhx - надо порядок навести. %p надо использовать.

    ОтветитьУдалить