17

在研究如何printf()用 C 语言处理跨平台格式字符串时(也就是说,考虑到我希望每个整数参数printf()应该具有的位数),我遇到了 .wikipedia 文章的这一部分printf()。本文讨论了可以传递给格式字符串的非标准选项printf(),例如(似乎是 Microsoft 特定的扩展):

printf("%I32d\n", my32bitInt);

它继续指出:

ISO C99 包含 inttypes.h 头文件,其中包含许多用于与平台无关的 printf 编码的宏。

...然后列出可以在所述标题中找到的一组宏。查看头文件,要使用它们,我必须写:

 printf("%"PRId32"\n", my32bitInt);

我的问题是:我错过了什么吗?这真的是标准的 C99 方法吗?如果是这样,为什么?(虽然我并不惊讶我从未见过以这种方式使用格式字符串的代码,因为它看起来很麻烦......)

4

5 回答 5

16

C Rationale 似乎暗示 <inttypes.h> 正在标准化现有实践:

<inttypes.h>派生自多个现有 64 位系统上的同名标头。

但是文本的其余部分没有写这些宏,我不记得它们当时是现有的做法。

以下内容只是推测,但受标准化委员会工作经验的启发。

C99 宏相对于为 printf 标准化附加格式说明符(请注意,C99 也确实添加了一些)的一个优势是,<inttypes.h><stdint.h>您已经有一个以特定于实现的方式支持所需功能的实现时,只需编写两个具有足够 typedef 的文件和宏。这降低了使现有实现符合标准的成本,降低了破坏利用现有实现细节特征的现有程序的风险(标准方式不干扰),并促进将符合标准的程序移植到没有这些的实现标头(它们可以由程序提供)。此外,如果当时特定的实现方式已经发生了变化,那么它不会偏向于一种实现。

于 2009-07-26T06:53:28.837 回答
8

正确,这就是 C99 标准所说的你应该使用它们的方式。如果您想要 100% 符合标准的真正可移植代码,您应该始终打印intusing"%d"int32_tusing "%"PRId32

但是,大多数人不会打扰,因为很少有不这样做会很重要的情况。除非您将代码移植到 Win16 或 DOS,否则您sizeof(int32_t) <= sizeof(int)可以int32_t假设int. 同样,along long几乎是普遍的 64 位(尽管不能保证一定是这样),因此将 a 打印int64_t为 a long long(例如,使用%llx说明符)也是安全的。

types int_fast32_t, int_least32_t, et al 几乎从未使用过,因此您可以想象它们相应的格式说明符使用得更少。

于 2009-07-26T04:11:49.460 回答
2

您始终可以向上转换并使用%jd格式intmax_t说明符。

printf("%jd\n", (intmax_t)(-2));

我曾经intmax_t表明 anyintXX_t可以使用,但简单地转换为long对于这种情况来说要好得多int32_t,然后使用%ld.

于 2011-11-05T14:22:31.920 回答
1

我只能推测为什么。我喜欢上面 AProgrammer 的回答,但是忽略了一个方面:您要向 printf 添加什么作为格式修饰符? 在 printf 格式字符串中使用数字已经有两种不同的方式(宽度和精度)。添加第三种数字来说明参数中有多少位精度会很棒,但是你要把它放在哪里而不会使人们感到困惑呢?不幸的是,C 语言的缺陷之一是 printf 的设计初衷不是可扩展的。

宏很糟糕,但是当您必须编写可跨 32 位和 64 位平台移植的代码时,它们是天赐之物。绝对救了我的培根。

我认为你的问题的答案为什么

  • 没有人能想到更好的方法来做到这一点,或者
  • 标准委员会无法就他们认为明显更好的任何事情达成一致。
于 2009-07-26T17:26:25.070 回答
1

另一种可能性:向后兼容。如果您向 或其他选项添加更多格式说明符printf,则某些 C99 之前的代码中的说明符可能会有不同的格式字符串解释。

通过 C99 更改,您不会更改printf.

于 2011-04-06T15:34:43.033 回答