当我在C ++中使用标准C头时,我通常更喜欢将标识符放入std
命名空间的表单,例如<cstdlib>
。但是,当我使用它们时,GCC还将名称放入全局命名空间,这意味着它将接受如下程序:
#include <cstddef>
std::size_t x;
size_t y;
int main() {}
此处,x
的声明是正确的,但如果我希望我的代码可移植,则应拒绝y
的声明。 (请注意,如果我包含<stddef.h>
而不是<cstddef>
,GCC 将正确拒绝x
的声明。
我可以让GCC拒绝上面的声明y
吗?
我编写了所有我能想到的迂腐和警告:
-std=c++17 -pedantic -Wall -Wextra -Wpedantic -Weffc++
这些似乎都没有阻止GCC接受非便携式表格。
我现在不确定我是否正确理解规则;我的知识来自CPP参考文献中的这一部分:
C兼容性标头
对于
xxx.h
形式的某些C标准库头文件,C ++标准库都包含一个 同名的标题和另一个标题cxxx
的标题。除了
complex.h
之外,C ++中包含的每个xxx.h
标头 标准库在全局命名空间中放置每个名称 相应的cxxx
标题将放在std
命名空间中。允许这些标题在
std
中声明相同的名称 命名空间,以及相应的cxxx
标头也是允许的 在全局命名空间中声明相同的名称:包括<cstdlib>
绝对提供std::malloc
,也可能提供::malloc
。 包括<stdlib.h>
肯定提供::malloc
,也可以提供std::malloc
。这甚至适用于功能和功能过载 这不属于C标准库。
对我而言,最后一段表明GCC的行为是允许的但不是必需的,因此依赖它是错误的。
答案 0 :(得分:3)
不幸的是,这些标头还必须定义相应c标头中的所有类型。
18.4.1标题提要 [cstdint.syn]
2标题定义所有类型和宏与C标准库标题
<stdint.h>
相同。
答案 1 :(得分:3)
规则是#include <xxx.h>
(其中xxx.h
是标准C标头的名称)是必需来定义该标头的C标准所需的所有名称在全局命名空间中,允许还在命名空间std
中定义这些名称(具有相同含义)。同样,#include <cxxx>
(其中cxxx
是标准C库的标准C ++标头之一的名称)是必需来定义相应C头中的所有名称(在命名空间std
中具有相同的含义,并且允许也在全局命名空间中定义这些名称。
回到C ++ 98,不允许那些标题添加到另一个名称空间。有些编译器无法做到这一点。例如,如果C ++库编写者不控制C头,那么通常的实现技术是将C ++头部#include
改为C头,并使用声明将C名称提升为std
。 。所以规则被改变以反映现实。
语言定义不要求这些标题将名称放在两个位置;如果确实如此,那么就不需要cxxx
标题。
简而言之,您不能依靠#include <cxxx>
将C名称放入全局命名空间,但您也无法依靠它而不是将它们放在那里。
答案 2 :(得分:0)
但如果我想要我的代码,应该拒绝y的声明 便携
请放心,您的代码将是可移植的:但遗憾的是,如果没有std::size_t
,则无法获取size_t
。这是因为#include <cstddef>
需要引入<stdint.h>
中定义的C类型。
因为你无法定义&#34; C ++中的一种类型,你唯一的办法是使用静态分析工具:然后你可以强制执行任何惹人喜爱的风格规则。