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

问题描述 投票:25回答:4

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

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

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

Questions

  1. 让我们说在size_t的情况下。为什么不简单地在stddef.h
  2. 假设一个C编译器在这些头文件中实现了size_t。它们是否保证在这些头文件中具有相同的定义?
c dry
4个回答
10
投票

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

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

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

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

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


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标准化委员会为标准库决定的内容。


6
投票

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

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

是的,size_t必须定义为指定的,(typedef unsigned long size_t; ):

typedef unsigned int size_t

要么

size_t

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

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


5
投票

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

当规范列出应该声明#include的“文件”时,它真正说的是命名任何一个文件的size_t指令应该在全局范围内创建该标识符。这可以通过让所有列出的名称的文件包含size_t的定义,或者将#include内置到编译器中,但只启用编译器的内置定义来查看带有指定名称之一的qazxswpoi指令。

© www.soinside.com 2019 - 2024. All rights reserved.