为什么在多个标准头文件中声明了特定的C数据类型?

Ast*_*oth 25 c dry

例如,C11规定size_t应在以下头文件中声明:

  • STDDEF.H
  • stdio.h中
  • stdlib.h中
  • string.h中
  • time.h中
  • uchar.h
  • wchar.h

在阅读C11时,我发现在多个标准头文件中声明了许多其他数据类型.

问题

  1. 让我们说的是size_t.为什么不只是stddef.h为了简单?
  2. 假设C编译器size_t在那些头文件中实现.它们是否保证在这些头文件中具有相同的定义?

tre*_*tcl 23

作为声明的函数的一个例子stdio.h,要求size_t是预先声明的,请考虑snprintf().实际上,如果您想在代码中使用它,您需要做的就是#include <stdio.h>.如果size_t仅在声明中stddef.h,则必须

#include <stddef.h>
#include <stdio.h>
Run Code Online (Sandbox Code Playgroud)

不仅如此,但由于stdio.h声明snprintf是否使用与否,你必须包括这两个文件每次你需要时间什么stdio.h,以避免编译器错误; stdio.h会有人为依赖stddef.h.这会导致您的源代码变得更长且更脆弱(请注意,如果您颠倒两个指令的顺序,它也会破坏).相反,我们编写头文件使它们独立并且不依赖于其他头文件,这就是C标准化委员会为标准库决定的内容.

  • 这是可信的,乍一看似乎合乎逻辑,但事实并非如此.`size_t`是特定预定义类型的typedef,系统头是特定于系统的.在`size_t`是例如`unsigned int`的typedef的系统上,如果实现声明`snprintf`为'unsigned int`而不是`size_t`,那么就没有问题(没有困难也没有一致性问题),所以不需要typedef. (3认同)

Kla*_*äck 10

假设size_t,我们假设.为简单起见,为什么不在stddef.h中呢?

该类型用于所有这些文件中的函数声明.如果没有声明,<stdio.h>除非你先包含,否则会出现编译错误<stddef.h>.

假设C编译器在这些头文件中实现了size_t.它们是否保证在这些头文件中具有相同的定义?

是的,他们将有相同的定义.通常,该值在单个位置定义在其他包含的单独包含文件中.

在某些情况下,可以使用编译器选项或定义来修改定义,例如,允许32/64位编译的编译器可以定义size_t为32位或64位无符号实体,具体取决于编译器命令行上定义的目标.

  • 或者`stdio.h`可以包含`stddef.h`. (2认同)

Tim*_*ost 6

byin之间存在细微差别- size_t只要在包含指定标头时定义了实现,就可以在单个标头中完全自由定义.那么,你有两个选择:

  1. size_t在每一个中定义并将每个包裹在包含警卫中
  2. 将其定义在单个文件中,并将其包含在包含保护中

是的,size_t 必须定义为指定的,即(glibc):

typedef unsigned long size_t;
Run Code Online (Sandbox Code Playgroud)

要么

typedef unsigned int size_t
Run Code Online (Sandbox Code Playgroud)

他们并没有说你必须理智,他们只是说它需要在任何人包含其中一个标题时定义,因为它们依赖于它被定义并且可以独立使用.简而言之,如果你定义依赖的东西size_t,那么size_t必须先(先前)定义.

你这样做(或者更确切地说,在哪里)取决于你的实现.

  • `size_t`不保证与`unsigned long`相同.而不是在LLP64实现上. (2认同)

sup*_*cat 5

首先,当一个人执行a时#include <stdio.h>,并不要求实际存在一个名为stdio.h的文件,或者编译器对这样的文件做任何事情.相反,要求是这样的行必须​​使得被指定为与之关联的所有标识符都<stdio.h>根据规范来定义.对于编译器来说,#include <stdio.h>只需启用使用硬编码到编译器中的某些标识符,这将是完全合法的.因为编译器供应商使事情按照规范要求#include <stdio.h>运行的最简单方法是让指令stdio.h通过预处理器运行某些文件的文本,这是许多编译器所做的,但这不是必需的.

当规范列出size_t应该声明的"文件"时,它真正说的是#include指定任何一个文件的指令应该在全局范围内创建该标识符.这可以通过使具有所有列出的名称的文件包含编译器的定义size_t或者size_t内置到编译器中但仅启用编译器的内置定义来查看具有#include指示名称之一的指令来完成.