这个问题涉及需要在POSIX/SUS标准所需的标头中定义的各种类型的类型。
某些类型需要在许多头文件中定义,我想知道实现这一目标的正确且合规的方法是什么。
例如,查看<time.h>
标头规范:
包含标题可能会使 <信号.h>标头。信号.h>
这很简单,<signal.h>
包含在<time.h>
中。
现在这个呢:
clock_t、size_t、time_t、clockid_t和 timer_t类型应如中所述定义 .
据我了解,这意味着我们不能简单地包含来自<time.h>
的<sys/types.h>
,因为这会暴露比所需更多的符号。
那么谁能证实这一点?包括<sys/types.h>
会违反标准合规性吗?
我认为最好的解决方案是为每种类型创建一个特定的标题,这样特定类型就可以从任何地方可见,而不必担心其他符号.
还有其他好的解决方案吗?
最后,C标准中的类型呢?
POSIX/SUS 规范中的许多类型都是整数类型,可能需要具有固定宽度。
那么,标准是否可以包含来自特定标头的<stdint.h>
,或者它会破坏合规性?
您是对的,从其他标头公开不需要的类型和声明是不合规的。
一个微不足道的(但是,就预处理器花费在打开文件上的时间而言,昂贵(解决方案是为每种类型提供一个单独的标头,并且在需要时,例如,time_t
,执行以下操作:
#include <types/time_t.h>
当然,types/time_t.h
会有适当的多包含保护。
还有许多其他方法可以实现相同的目标。glibc 和 gcc 使用的方法是在包含要求它只提供一种或多种类型的标头之前定义特殊的"需要"宏。这个解决方案也非常昂贵,可能比上述更昂贵,因为它打破了编译器对多包含保护的启发式方法。编译器无法省略重复的包含;每次包含文件时,它都必须解析文件。
我们在 musl 中这样做的方法是有一个文件, bits/alltypes.h
,其中包括多个标头和宏所需的所有类型的定义,以控制公开哪些。它由一个简单的 sed 脚本生成,该脚本隐藏了所有宏逻辑:
- http://git.musl-libc.org/cgit/musl/tree/arch/i386/bits/alltypes.h.in?id=9448b0513e2eec020fbca9c10412b83df5027a16
- http://git.musl-libc.org/cgit/musl/tree/include/alltypes.h.in?id=9448b0513e2eec020fbca9c10412b83df5027a16
- http://git.musl-libc.org/cgit/musl/tree/tools/mkalltypes.sed?id=9448b0513e2eec020fbca9c10412b83df5027a16
在阅读这个问题时,我忍不住检查了有史以来最大的 UNIX 兼容(严格来说,只有"类 UNIX"(开源项目 - Linux 内核(现在几乎总是担心标准合规性(。
一个示例实现:
time.h
标头将定义一些内部标志,然后包含定义所有类型的types.h
,尽管在 #ifdef
秒内检查是否定义了某些内部标志。
所以这归结为以下内容:
- 定义模块化标头,例如
time.h
-
#define
相关的内部标志以建立上下文。 - 包括提供依赖项的"内部"标头。
- 实现"内部"标头,以便它们根据
#include
-ed 的上下文有选择地公开功能。
通过这种方式,可以提供模块化标头以供包含,而不必担心意外公开比所需更多的符号。