如何打印 off_t 和 size_t 这样的类型?

我正在尝试打印类型,如 off_tsize_tprintf() 这是便携式的的正确占位符是什么?

或者有完全不同的方式来打印这些变量?

154480 次浏览

你用的是哪个版本的 C?

在 C90中,标准实践是将其转换为有符号或无符号的长度,并相应地打印。我已经看到了 size _ t 的% z,但 Harbison 和 Steele 没有在 printf ()下提到它,而且在任何情况下,它都不会帮助您处理 ptrdiff _ t 或其他任何东西。

在 C99中,各种 _ t 类型都有自己的 printf 宏,所以像 "Size is " FOO " bytes."这样的东西我不知道细节,但它是一个相当大的数字格式包含文件的一部分。

据我回忆,唯一可移植的方法是将结果转换为“ unsignedlongint”并使用 %lu

printf("sizeof(int) = %lu", (unsigned long) sizeof(int));

查看 Linux、 OS X 和 OpenBSD 上的 man 3 printf都显示了对 %z for size_t%t for ptrdiff_t(for C99)的支持,但是没有一个提到 off_t。建议在野外通常提供 %u转换为 off_t,这是“足够正确的”,因为我可以告诉(无论是 unsigned intoff_t之间的64位和32位系统完全不同)。

可以使用 z表示 size _ t,使用 t表示 ptrdiff _ t,如

printf("%zu %td", size, ptrdiff);

但是我的手册上说,一些较老的库使用了与 z不同的字符,因此不鼓励使用它。然而,它是标准化的(按照 C99标准)。对于那些 stdint.hintmax_tint8_t等等,你可以使用宏,就像另一个答案所说的:

printf("value: %" PRId32, some_int32_t);
printf("value: %" PRIu16, some_uint16_t);

它们在 inttypes.h的页面中列出。

就我个人而言,我只是将值强制转换为 unsigned longlong,就像另一个答案建议的那样。如果使用 C99,那么可以(当然也应该)转换为 unsigned long longlong long,并分别使用 %llu%lld格式。

您需要使用 inttypees.h 中的格式化宏。

看这个问题: 大小 _ t 类型变量的跨平台格式字符串?

对 off _ t 使用“% zo”(八进制) 或者“% zu”表示小数。

打印 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兼容,但是不支持“[ t ] he hh,j,z 和 t 长度前缀”对于 size _ t “也就是说,32位平台上的 unsigned _ _ int32,64位平台上的 unsigned _ _ int64”使用前缀 I (大写眼)和类型说明符 o、 u、 x 或 X

对于 off _ t,它在 VC 中定义为 long include sys typees.h。

我至少看了这篇文章两次,因为我很难记住被接受的答案(我很少使用 zj标志,它们似乎不是 独立平台)。

标准从来没有清楚地说明 size_t的确切数据长度,所以我建议你首先检查平台上的 size_t长度,然后选择其中之一:

if sizeof(size_t) == 4 use PRIu32
if sizeof(size_t) == 8 use PRIu64

为了保持一致性,我建议使用 stdint类型而不是原始数据类型。

如果使用 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);

不会工作,这使得它在许多情况下无用。是的,您可以在运行时组合字符串,但这很烦人。