Я пытаюсь напечатать такие типы, как off_t
и size_t
. Каков правильный заполнитель для printf()
этого портативного ?
Или есть совершенно другой способ печати этих переменных?
Я пытаюсь напечатать такие типы, как 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
соответственно.
%zd
с size_t
является неопределенным поведением из-за несоответствия подписи (C99 7.19.6.1 # 9). Должно быть %zu
.
%zd
с помощью size_t
получить неопределенное поведение из этого абзаца или из любого другого. Фактически, определение %z
в # 7 явно разрешает %d
с size_t
и соответствующий тип со знаком, а §6.2.5 # 9 явно позволяет использовать значения беззнаковых типов, где ожидается соответствующий тип со знаком, при условии, что значение является действительным неотрицательным значением подписанного типа.
Для печати 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
, что не получится в некоторых других реализациях, потому что он слишком мал.
ssize_t
имеет тот же размер size_t
, что и действительно переносимый код, должен преобразовывать его в intmax_t
и печатать так %jd
же, как off_t
.
Для 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.
off_t
всегда long
, это сделает его 32-битным (даже для 64-битной Windows используется 32-битная версия long
).
Какую версию C вы используете?
В C90 стандартной практикой является приведение к подписанному или неподписанному длинному, в зависимости от ситуации, и печати соответственно. Я видел% z для size_t, но Харбисон и Стил не упоминают об этом в printf (), и в любом случае это не поможет вам с ptrdiff_t или чем-то еще.
В C99 различные типы _t поставляются со своими собственными макросами printf, так что "Size is " FOO " bytes."
я не знаю деталей, но это часть довольно большого числового формата включаемого файла.
Вы захотите использовать макросы форматирования из inttypes.h.
Смотрите этот вопрос: Строка формата кроссплатформенного для переменных типа size_t?
off_t
Типа больше , чем указатель на любой 32-битной системе , которая поддерживает большие файлы (что большинство 32-битные системы в эти дни).
Рассматривая в 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-битных систем).
unsigned int
и 64-разрядную версию off_t
. Таким образом, приведение может привести к потере данных.
Я видел этот пост по крайней мере дважды, потому что принятый ответ трудно запомнить для меня (я редко использую z
или j
отмечаю флаги, и они, кажется, не зависят от платформы ).
В стандарте никогда точно не указывается точная длина данных size_t
, поэтому я советую сначала проверить длину size_t
на своей платформе, а затем выбрать один из них:
if sizeof(size_t) == 4 use PRIu32
if sizeof(size_t) == 8 use PRIu64
И я предлагаю использовать stdint
типы вместо необработанных типов данных для согласованности.
%zu
можно использовать для печати size_t
значений. Определенно не следует прибегать к использованию спецификатора uint32_t
/ uint64_t
format для печати a size_t
, поскольку нет гарантии, что эти типы совместимы.
Насколько я помню, единственный переносимый способ сделать это - привести результат к «unsigned long int» и использовать %lu
.
printf("sizeof(int) = %lu", (unsigned long) sizeof(int));
long long
что не существует в стандарте C ++ и, следовательно, по своей сути не переносимы.
fopen
,fseek
и т.д. на Mac OS X.off_t
используется для смещения.