为什么不是新的(特定于位宽)printf()格式选项字符串作为C99的一部分?

在研究如何在C中执行跨平台printf()格式字符串时(也就是考虑到我希望每个整数参数对printf()的位数应该是)我在printf()上浏览维基百科文章的这一部分printf() 。 本文讨论了可以传递给printf()格式字符串的非标准选项,例如(似乎是特定于Microsoft的扩展名):

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

它接着说:

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

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

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

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

C原理似乎暗示正在标准化现有实践:

源自几个现有64位系统上的同名头。

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

接下来只是猜测,但受到标准化委员会工作经验的教育。

C99宏优于标准化printf的其他格式说明符(注意C99也添加了一些)的一个优点是,当您已经拥有支持特定实现中所需function的实现时,提供方法就是用足够的typedef和宏编写两个文件。 这降低了使现有实施符合要求的成本,降低了破坏现有程序的风险,这些程序利用了现有的实现细节function(标准方式不会干扰),并便于将符合性程序移植到没有这些程序的实现中标题(它们可以由程序提供)。 此外,如果当时实现特定方式已经变化,则不会优先于一个实现而不是另一个实现。

正确,这就是C99标准所说你应该使用它们的方式。 如果你想要真正符合字母100%标准的portablt代码,你应该总是使用"%d"和使用"%"PRId32int32_t打印一个int

但是,大多数人都不会打扰,因为很少有人不这样做会很重要。 除非您将代码移植到Win16或DOS,否则您可以假设sizeof(int32_t) <= sizeof(int) ,因此意外地将int32_t作为int int32_t是无害的。 同样, long long通常是64位(尽管不能保证这样),因此将int64_t打印为long long (例如使用%llx说明符)也是安全的。

int_fast32_tint_least32_t等类型几乎从未使用过,因此您可以想象它们相应的格式说明符的使用率更低。

您始终可以向上投射并使用%jd ,它是intmax_t格式说明符。

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

我使用intmax_t来表明可以使用任何intXX_t ,但是对于int32_t情况,简单地转换为long更好,然后使用%ld

我只能推测为什么。 我喜欢上面的AProgrammer的答案,但忽略一个方面: 你打算将什么作为格式修饰符添加到printf? 在printf格式字符串中使用数字已经有两种不同的方式(宽度和精度)。 添加第三种数字来说明参数中的精确位数会很好,但是你要把它放在哪里而不会让人混淆? 不幸的是,C中的一个缺点是printf的设计并不是可扩展的。

这些宏很糟糕,但是当你必须编写可在32位和64位平台上移植的代码时,它们是天赐之物。 绝对保存了我的培根。

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

  • 没有人能想到更好的方法,或者
  • 标准委员会无法就他们认为明显更好的任何事情达成一致。

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

通过C99更改,您无需更改printf的function。