Как мне печатать такие типы, как off_t и size_t? - PullRequest
140 голосов
/ 25 февраля 2009

Я пытаюсь напечатать такие типы, как off_t и size_t. Каков правильный заполнитель для printf() , который является переносимым ?

Или есть ли совершенно другой способ печати этих переменных?

Ответы [ 9 ]

102 голосов
/ 25 февраля 2009

Вы можете использовать z для size_t и t для ptrdiff_t, как в

printf("%zu %zd", 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 соответственно.

99 голосов
/ 09 марта 2011

Для печати 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, что не получится в некоторых других реализациях, потому что оно слишком мало.

5 голосов
/ 20 марта 2014

Для Microsoft ответ другой. VS2013 в значительной степени совместим с C99, но «префиксы длины [t] he hh, j, z и t не поддерживаются». Для size_t «то есть без знака __int32 на 32-битных платформах, без знака __int64 на 64-битных платформах» использовать префикс I (заглавная) с указателем типа o, u, x или X. См. спецификацию размера VS2013

Что касается off_t, он определяется как long в VC \ include \ sys \ types.h.

3 голосов
/ 25 февраля 2009

Вы захотите использовать макросы форматирования из inttypes.h.

См. Этот вопрос: Строка формата для разных платформ для переменных типа size_t?

3 голосов
/ 25 февраля 2009

Какую версию C вы используете?

В C90 стандартной практикой является приведение к подписанному или неподписанному длинному, в зависимости от случая, и печати соответственно. Я видел% z для size_t, но Харбисон и Стил не упоминают об этом в printf (), и в любом случае это не поможет вам с ptrdiff_t или чем-то еще.

В C99 различные типы _t поставляются со своими собственными макросами printf, поэтому что-то вроде "Size is " FOO " bytes." Я не знаю деталей, но это часть довольно большого числового формата включаемого файла.

1 голос
/ 25 февраля 2009

Глядя на 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-битных системах) .

0 голосов
/ 14 октября 2016

Я видел этот пост по крайней мере дважды, потому что принятый ответ трудно запомнить для меня (я редко использую z или j флаги, и они, кажется, не независимы от платформы ).

Стандарт никогда точно не говорит точную длину данных size_t, поэтому я предлагаю вам сначала проверить длину size_t на своей платформе, а затем выбрать один из них:

if sizeof(size_t) == 4 use PRIu32
if sizeof(size_t) == 8 use PRIu64

И я предлагаю использовать stdint типы вместо типов необработанных данных для согласованности.

0 голосов
/ 26 марта 2010

используйте "% zo" для off_t. (Восьмеричное) или "% zu" для десятичного числа.

0 голосов
/ 25 февраля 2009

Насколько я помню, единственный переносимый способ сделать это - привести результат к unsigned long int и использовать %lu.

printf("sizeof(int) = %lu", (unsigned long) sizeof(int));
...