Я пытаюсь напечатать такие типы, как 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 printfLinux, 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_tformat для печати 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используется для смещения.