Я намагаюся друкувати такі типи, як 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
з a 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, то він визначений, поки у 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
формату для друку size_t
, оскільки немає гарантії сумісності цих типів.
Як я пам’ятаю, єдиний портативний спосіб це зробити - це передавати результат на «неподписаний довгий int» та використовувати %lu
.
printf("sizeof(int) = %lu", (unsigned long) sizeof(int));
long long
вона не існує в стандарті C ++, і, таким чином, вона по суті не переносна.
fopen
,fseek
і т.д. на Mac OS X.off_t
використовується для зсуву.