我正在尝试打印off_t
和size_t
. printf()
什么是可移植的正确占位符?
或者是否有完全不同的方式来打印这些变量?
我正在尝试打印off_t
和size_t
. printf()
什么是可移植的正确占位符?
或者是否有完全不同的方式来打印这些变量?
您可以使用z
for size_t 和t
for 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
orlong long
和使用%llu
or%lld
格式。
打印off_t
:
printf("%jd\n", (intmax_t)x);
打印size_t
:
printf("%zu\n", x);
打印ssize_t
:
printf("%zd\n", x);
请参阅 C99 标准中的 7.19.6.1/7,或更方便的格式化代码的 POSIX 文档:
http://pubs.opengroup.org/onlinepubs/009695399/functions/fprintf.html
如果您的实现不支持这些格式代码(例如,因为您在 C89 上),那么您会遇到一些问题,因为 AFAIK 在 C89 中没有具有格式代码的整数类型,并且保证一样大作为这些类型。所以你需要做一些特定于实现的事情。
例如,如果您的编译器具有long long
并且您的标准库支持%lld
,您可以自信地期望它将代替intmax_t
. 但如果没有,您将不得不回退到long
,这在其他一些实现中会失败,因为它太小了。
对于微软来说,答案是不同的。VS2013 在很大程度上符合 C99,但“不支持 hh、j、z 和 t 长度前缀。” 对于 size_t “即 32 位平台上的无符号 __int32,64 位平台上的无符号 __int64”使用前缀 I(大写眼睛)和类型说明符 o、u、x 或 X。 请参阅 VS2013 大小规范
至于off_t,在VC\include\sys\types.h中定义为long。
你用的是哪个版本的C?
在 C90 中,标准做法是酌情转换为有符号或无符号长,并相应地打印。我见过 size_t 的 %z,但是 Harbison 和 Steele 没有在 printf() 下提到它,而且无论如何这对 ptrdiff_t 或其他什么都没有帮助。
在 C99 中,各种 _t 类型都有自己的 printf 宏,所以"Size is " FOO " bytes."
我不知道细节,但这是相当大的数字格式包含文件的一部分。
您需要使用 inttypes.h 中的格式化宏。
请参阅此问题: size_t 类型变量的跨平台格式字符串?
查看man 3 printf
Linux、OS X 和 OpenBSD 都显示了对%z
forsize_t
和%t
for ptrdiff_t
(for C99) 的支持,但没有一个提到off_t
. 野外的建议通常会提供 的%u
转换off_t
,据我所知,这是“足够正确的”(两者在 64 位和 32 位系统之间变化相同)unsigned int
。off_t
如果您使用 C11 或 C18,则可以使用_Generic
.
#include <stdio.h>
#include <sys/types.h>
#define TYPE_FORMAT(variable) _Generic \
( \
(variable) \
, unsigned char : "%hhu" \
, unsigned short : "%hu" \
, unsigned int : "%u" \
, unsigned long : "%lu" \
, unsigned long long : "%llu" \
, signed char : "%hhi" \
, signed short : "%hi" \
, signed int : "%i" \
, signed long : "%li" \
, signed long long : "%lli" \
)
int main(void)
{
off_t a=3321;
printf(TYPE_FORMAT(a), a);
}
但是,有一个主要缺点:您不能以这种方式组合字符串。这意味着:
printf("Foo: " TYPE_FORMAT(a), a);
将不起作用,这使得它在许多情况下无用。是的,您可以在运行时组合字符串,但这很烦人。
我记得,唯一可移植的方法是将结果转换为“unsigned long int”并使用%lu
.
printf("sizeof(int) = %lu", (unsigned long) sizeof(int));
对 off_t 使用“%zo”。(八进制)或十进制的“%zu”。