Я намагаюся друкувати такі типи, як 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використовується для зсуву.