为什么 stdio.h、stdlib.h、string.h 声明 size_t、NULL 等而不是 #include <stddef.h>?

Why stdio.h, stdlib.h, string.h declare size_t, NULL, etc. instead of #include <stddef.h>?

headers stdio.h, stdlib.h, string.h 声明 size_t, NULL, 等等

为什么要声明 size_tNULL 等而不是 #include <stddef.h>

因为这是 C 标准所说的:

http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf

ISO/IEC 9899:TC3 Committee Draft — Septermber 7, 2007 WG14/N1256

7.19 Input/output <stdio.h>

7.19.1 Introduction

1 The header <stdio.h> declares three types, several macros, and many functions for performing input and output.

2 The types declared are size_t (described in 7.17);

[...]

3 The macros are NULL (described in 7.17);

7.17 实际上是 <stddef.h>.

的部分

Why declaring size_t, NULL, etc. instead of #include <stddef.h>?

根据 C17 7.19/3,stddef.h 确实 定义了 NULL,所以这个问题是没有根据的。由于前提似乎部分是 stddef.h 所扮演的角色使其成为定义 NULL 的好地方,标准委员会似乎同意。

stdio.h (7.21.1/2)、stdlib.h (7.22/3) 和 string.h (7.24.1/1) 也定义了 NULL。至于为什么会这样,我倾向于说历史变化的组合,其中 headers 定义了哪些宏起作用,但也有这样的情况,这些 headers 中的每一个都声明在至少一个函数,其参数和/或 return 值将特定意义赋予空指针。例如,fopen() return在失败时是一个空指针。尽管使用宏 NULL 来表示空指针常量不是必需的,但它是高度惯用的,因此确保这些 header 定义它至少可以在大多数标准库情况下访问它在需要的地方,不需要为了那个目的而包含 header。

类似适用于 size_t,减去历史变化角度。

附录

经过复习,我想我最初看错了问题。然而,在某种程度上,它询问了为什么规范说 stdio.h etc。定义也由 stddef.h 定义的各种标识符,当它可以指定那些 headers #include <stddef.h> 时,我认为它仍然主要归结为每个 header 提供所有它需要的声明,以便基本上独立存在。

然而,另外,如果规范说(例如)string.h 包含 stddef.h 那么这将使所有指定的标识符在任何情况下都被后者保留(在各种意义上)声明根据规范第 7.1.3 节,包括前者的翻译单元。通过指定在 string.h 中声明或定义的特定标识符,仅通过包含 string.h.

保留那些特定标识符