157

我正在尝试打印off_tsize_t. printf() 什么是可移植的正确占位符?

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

4

10 回答 10

121

您可以使用zfor size_t 和tfor ptrdiff_t 像

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

但是我的手册页说一些较旧的库使用了不同的字符,z并且不鼓励使用它。不过,它是标准化的(按照 C99 标准)。对于那些intmax_t等等int8_tstdint.h您可以使用宏,就像另一个答案所说:

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

它们列在inttypes.h.

就个人而言,我只会将值转换为unsigned longlong喜欢另一个答案推荐的值。如果您使用 C99,那么您可以(当然也应该)分别转换为unsigned long longorlong long和使用%lluor%lld格式。

于 2009-02-25T17:38:34.323 回答
117

打印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,这在其他一些实现中会失败,因为它太小了。

于 2011-03-09T20:44:52.897 回答
5

对于微软来说,答案是不同的。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。

于 2014-03-20T15:39:47.287 回答
3

你用的是哪个版本的C?

在 C90 中,标准做法是酌情转换为有符号或无符号长,并相应地打印。我见过 size_t 的 %z,但是 Harbison 和 Steele 没有在 printf() 下提到它,而且无论如何这对 ptrdiff_t 或其他什么都没有帮助。

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

于 2009-02-25T17:20:32.247 回答
3

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

请参阅此问题: size_t 类型变量的跨平台格式字符串?

于 2009-02-25T17:39:57.050 回答
1

查看man 3 printfLinux、OS X 和 OpenBSD 都显示了对%zforsize_t%tfor ptrdiff_t(for C99) 的支持,但没有一个提到off_t. 野外的建议通常会提供 的%u转换off_t,据我所知,这是“足够正确的”(两者在 64 位和 32 位系统之间变化相同)unsigned intoff_t

于 2009-02-25T17:37:30.380 回答
1

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

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

于 2021-07-30T21:16:44.860 回答
-3

我至少看过这篇文章两次,因为接受的答案对我来说很难记住(我很少使用zorj标志,它们似乎与平台无关)。

标准从未明确说明 的确切数据长度size_t,因此我建议您首先检查size_t平台上的长度,然后选择其中一个:

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

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

于 2016-10-14T08:30:13.080 回答
-4

我记得,唯一可移植的方法是将结果转换为“unsigned long int”并使用%lu.

printf("sizeof(int) = %lu", (unsigned long) sizeof(int));
于 2009-02-25T17:20:50.497 回答
-9

对 off_t 使用“%zo”。(八进制)或十进制的“%zu”。

于 2010-03-26T11:19:10.307 回答