实施 PRI 宏 'portably'

Implementing PRI macros 'portably'

指定的 C99 inttypes.h header 包含为 stdint.h 提供的 fixed-width 整数类型(以 PRI 开头)提供格式说明符的宏。虽然 stdint.h 在 header 的 'freestanding' 列表中,因此始终由实现提供,但 inttypes.h 不是。

这意味着在为非托管环境(例如bare-metal)编译时,如果您想提供可以处理[=23]的standards-compliant printf,则必须自己提供inttypes.h =]类型。

但是,如果不手动检查实现的 stdint.h,我不知道如何在 compile-time 处正确确定每个宏应该是什么,这项任务不仅需要针对每个目标重复进行平台,但适用于每个支持的编译器。

我尝试通过 C11 的 _Generic 实现,但是

有没有标准的方法来做到这一点?

这是不可能的。本质上,inttypes.h存在给你可移植性,你不能“猜”到它。它必须由编译器给出。最重要的是,理论上,可能不存在 printf 格式说明符来打印 stdint.

中的类型

a standard way to do this?

是 - 请联系您的编译器提供商并提出功能请求。在等待它的同时,阅读您的编译器文档 and/or 源代码或联系上游以获取更多信息,并使用您需要的信息创建您自己的 myinttypes.h

standards-compliant printf that can handle fixed-width types.

这很简单 - 在打印之前将类型转换为标准类型。 64_tlong long32_tlong16_tint8_tchar 并打印他们使用标准 %lld...%hhd 格式说明符。

you must provide inttypes.h

不能保证提供 inttypes.h,这不能保证不提供 - 可能会提供。这个问题听起来更像是一个理论问题——我不认为没有 inttypes.h.

的任何常见编译器

This means that when compiling for an unhosted environment (say bare-metal), you must provide inttypes.h yourself if you want to provide a standards-compliant printf that can handle fixed-width types.

不,根本不是那个意思。

也许您对 fixed-width 类型的认识有误。由给定实现提供的那些(根本不需要它们中的任何一个)通常是该实现的标准整数类型。 stdint.h 中声明的类型名称是适当标准类型的 别名 ,而不是扩展整数类型的名称。

因此,有问题的宏定义的字符串文字通常包含 标准 转换说明符,可能带有长度修饰符,例如 "d""hu",或"lx"。如果你想提供一个 printf 与托管环境提供的兼容,那么你需要支持所有标准转换说明符和所有与每个相关的长度修饰符,完全不考虑这些宏是否被定义或他们的替换文本可能是什么。

我想您可能 运行 进入一个提供 fixed-width 类型的实现(甚至是托管的实现),而实际上它并没有在其标准整数类型中使用。要使用 printf 支持此类类型,您可能需要扩展它以提供新的转换说明符,但在这种情况下,这是 printf 实现的一部分,因此您知道如何定义相应的宏.

无论如何,宏仅与 printf 调用者相关,与实施者无关,除非您可能会发现编写这些宏的定义与实施 printf 相结合会很方便。

I cannot figure out how to correctly determine at compile-time what each macro should be without manually inspecting the implementation's stdint.h [...] Is there a standard way to do this?

没有。这就是为什么首先 由实现 提供宏的原因。但是,来电者不一定需要知道。他们可以将他们的 fixed-width 类型转换为他们实现的 guaranteed-wide-enough 标准类型,并为该类型使用正确的标准转换说明符。 printf 既便宜又简单。但是,如果你也想提供一个scanf,那么相应的适配器代码就有点不方便了。