例如,C11规定应在以下头文件中声明size_t
:
当读取C11时,我发现在多个标准头文件中声明了许多其他数据类型。
size_t
的情况下说。为简单起见,为什么不在stddef.h
?size_t
。它们是否保证在这些头文件中具有相同的定义?答案 0 :(得分:22)
作为stdio.h
中声明的要求size_t预先声明的函数的示例,请考虑snprintf()
。实际上,如果您想在代码中使用它,您需要做的只是#include <stdio.h>
。如果size_t仅在stddef.h
中声明,则必须
#include <stddef.h>
#include <stdio.h>
不仅如此,但由于stdio.h
声明snprintf
无论您是否使用它,您都必须在每时间包含两个文件你需要stdio.h
中的任何来避免编译错误; stdio.h
会对stddef.h
产生人为依赖。这会导致您的源代码变得更长且更脆弱(请注意,如果您颠倒两个指令的顺序,它也会破坏)。相反,我们编写头文件以使它们独立并且不依赖于其他头文件,这就是C标准化委员会为标准库决定的内容。
答案 1 :(得分:10)
在size_t的情况下,让我们说。为简单起见,为什么不在stddef.h中?
该类型用于所有这些文件中的函数声明。如果它未在<stdio.h>
中声明,除非您首先包含<stddef.h>
,否则您将收到编译错误。
让我们说C编译器在这些头文件中实现size_t。它们是否保证在这些头文件中具有相同的定义?
是的,他们将有相同的定义。通常,该值在单个位置定义在其他包含文件中。
在某些情况下,可以使用编译器选项或定义来修改定义,例如,允许32/64位编译的编译器可以将size_t
定义为32位或64位无符号实体,具体取决于目标在编译器命令行上定义。
答案 2 :(得分:6)
by 和 之间存在细微差别 - 只需一个实体就可以在单个标头中定义size_t
。 #39;在包含指定标题时定义。所以,你有两个选择:
size_t
并将每个包裹在包含警卫是的,size_t 必须定义为指定的,(glibc):
typedef unsigned long size_t;
或
typedef unsigned int size_t
他们并不是说你必须保持理智,他们只是说当任何人包含其中一个标题时需要定义它,因为它们依赖于它被定义并且可以独立使用。简而言之,如果您定义依赖于size_t
的内容,则必须首先(先前)定义size_t
。
你这样做(或者更确切地说,在哪里)取决于你的实施。
答案 3 :(得分:5)
首先,当一个人执行#include <stdio.h>
时,并不要求实际存在任何名为stdio.h的文件,或者编译器对这样的文件执行任何操作。相反,要求是这样的行必须使得所有被指定为与<stdio.h>
相关联的标识符根据规范来定义。对于编译器而言,#include <stdio.h>
只是允许使用硬编码到编译器中的某些标识符,这是完全合法的。因为编译器供应商使事情符合规范要求的最简单方法是让#include <stdio.h>
指令通过预处理器运行某个文件stdio.h
的文本,这是许多编译器所做的,但是这不是必需的。
当规范列出&#34;文件&#34;应该声明size_t
的地方,它真正说的是命名任何一个文件的#include
指令应该在全局范围内创建该标识符。这可以通过使具有所有列出的名称的文件包含size_t
的定义,或者通过将size_t
内置到编译器中但仅启用编译器的内置定义来查看{{{ 1}}指令,带有一个指定的名称。