Как мне печатать такие типы, как off_t и size_t?
-
06-09-2019 - |
Вопрос
Я пытаюсь напечатать такие типы, как off_t
и size_t
.Каков правильный заполнитель для printf()
это портативный?
Или есть совершенно другой способ распечатать эти переменные?
Решение
Вы можете использовать z
для size_t и t
для ptrdiff_t, как в
printf("%zu %td", size, ptrdiff);
Но на моей странице руководства написано, что в какой-то старой библиотеке использовался другой символ, чем z
и препятствует его использованию.Тем не менее, он стандартизирован (по стандарту C99).Для тех intmax_t
и int8_t
из stdint.h
и так далее, есть макросы, которые вы можете использовать, как сказано в другом ответе:
printf("value: %" PRId32, some_int32_t);
printf("value: %" PRIu16, some_uint16_t);
Они перечислены на странице руководства inttypes.h
.
Лично я бы просто привел значения к unsigned long
или long
как рекомендует другой ответ.Если вы используете C99, то вы можете (и должны, конечно) приводить к unsigned long long
или long long
и используйте %llu
или %lld
форматы соответственно.
Другие советы
Печатать off_t
:
printf("%jd\n", (intmax_t)x);
Печатать size_t
:
printf("%zu\n", x);
Печатать ssize_t
:
printf("%zd\n", x);
См. 7.19.6.1/7 в стандарте C99 или более удобную документацию POSIX по кодам форматирования:
http://pubs.opengroup.org/onlinepubs/009695399/functions/fprintf.html
Если ваша реализация не поддерживает эти коды форматирования (например, потому что вы используете C89), то у вас возникла небольшая проблема, поскольку AFAIK в C89 нет целочисленных типов, которые имеют коды форматирования и гарантированно будут такими же большими. как эти типы.Поэтому вам нужно сделать что-то специфичное для реализации.
Например, если ваш компилятор имеет long long
и ваша стандартная библиотека поддерживает %lld
, вы можете с уверенностью ожидать, что послужит вместо intmax_t
.Но если этого не произойдет, вам придется вернуться к long
, который не работает в некоторых других реализациях, поскольку он слишком мал.
Для Microsoft ответ другой.VS2013 в значительной степени соответствует C99, но «[T] HH, J, Z и префиксы длины T не поддерживаются». Для size_t ", то есть unsigned __int32 на 32-разрядных платформах, unsigned __int64 на 64-битных платформах" Используйте префикс I (Capital Eye) с типом спецификатора O, U, X или X. См. спецификацию размера VS2013.
Что касается off_t, то он определен как long в VC\include\sys ypes.h.
Какую версию C вы используете?
В C90 стандартной практикой является приведение к знаковому или беззнаковому длинному типу, в зависимости от ситуации, и печать соответственно.Я видел %z для size_t, но Харбисон и Стил не упоминают об этом в printf(), и в любом случае это не поможет вам с ptrdiff_t или чем-то еще.
В C99 различные типы _t имеют свои собственные макросы printf, поэтому что-то вроде "Size is " FOO " bytes."
Я не знаю подробностей, но это часть включаемого файла довольно большого числового формата.
Вам понадобится использовать макросы форматирования из inttypes.h.
Смотрите этот вопрос: Строка межплатформенного формата для переменных типа size_t?
Смотря на man 3 printf
в Linux, OS X и OpenBSD все поддерживают %z
для size_t
и %t
для ptrdiff_t
(для C99), но ни один из них не упоминает off_t
.Предложения в дикой природе обычно предлагают %u
преобразование для off_t
, что, насколько я могу судить, "достаточно правильно" (оба unsigned int
и off_t
одинаково различаются между 64-битными и 32-битными системами).
Я видел этот пост как минимум дважды, потому что мне трудно запомнить принятый ответ (я редко использую z
или j
флаги, и они, кажется, нет независимая от платформы).
А стандартный никогда не говорит четко точную длину данных size_t
, поэтому я предлагаю вам сначала проверить длину size_t
на вашей платформе, затем выберите один из них:
if sizeof(size_t) == 4 use PRIu32
if sizeof(size_t) == 8 use PRIu64
И я предлагаю использовать stdint
типы вместо необработанных типов данных для обеспечения согласованности.
Насколько я помню, единственный переносимый способ сделать это — привести результат к «unsigned long int» и использовать %lu
.
printf("sizeof(int) = %lu", (unsigned long) sizeof(int));
используйте «%zo» для off_t.(восьмиугольный) или «%Zu» для десятичных.