Я пытаюсь напечатать такие типы, как off_t
и size_t
. Каков правильный заполнитель для printf()
этого портативного ?
Или есть совершенно другой способ печати этих переменных?
c
portability
format-specifiers
Георг Шолли
источник
источник
fopen
,fseek
и т.д. на Mac OS X.off_t
используется для смещения.Ответы:
Вы можете использовать
z
для size_t иt
для ptrdiff_t, как вНо моя справочная страница гласит, что в какой-то более старой библиотеке использовался символ, отличающийся от используемого,
z
и не одобряет его использование. Тем не менее, он стандартизирован (по стандарту C99). Для техintmax_t
иint8_t
другихstdint.h
и так далее, вы можете использовать макросы, как сказал другой ответ:Они перечислены на странице руководства
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
:Для печати
size_t
:Для печати
ssize_t
:См. 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
на своей платформе, а затем выбрать один из них:И я предлагаю использовать
stdint
типы вместо необработанных типов данных для согласованности.источник
%zu
можно использовать для печатиsize_t
значений. Определенно не следует прибегать к использованию спецификатораuint32_t
/uint64_t
format для печати asize_t
, поскольку нет гарантии, что эти типы совместимы.Насколько я помню, единственный переносимый способ сделать это - привести результат к «unsigned long int» и использовать
%lu
.источник
long long
что не существует в стандарте C ++ и, следовательно, по своей сути не переносимы.используйте "% zo" для off_t. (восьмеричное) или "% zu" для десятичного числа.
источник