C ++标准库头可以包含C标准头吗?

时间:2016-06-02 10:26:43

标签: c++ c c++-standard-library

我只能在标准草案N4582中找到

  

[res.on.headers / 1] C ++标头可能包含其他C ++标头。

似乎没有指定C ++标头是否可以包含C标准标头。

如果允许,即使不包含此标头,使用C标准头中定义的全局名称是否不安全(因为程序可能通过某些C ++标准头隐式包含头)?

3 个答案:

答案 0 :(得分:4)

C ++标准的D.3 C standard library headers部分使26 C标准头部成为C ++的一部分。因此,这些是C ++的一部分。此外,许多其他C标头都遵循语言的共享子集(可能通过#ifdef来解决一些问题),使它们成为有效的C和C ++标头。

答案 1 :(得分:4)

对于你跟进的问题(名称冲突),是的,它当然可以。原因是C ++标准库包含C标准库内容的<c:::> C ++标头,标准明确允许它们在全局命名空间中提供名称(除了强制在{{{{1}中提供它们之外1}})。

此外,根据C ++标准的附录D [depr],C标准库头文件(::std版本)也是C ++标准库的一部分(尽管已弃用)。这意味着[res.on.headers] / 1允许C ++标题包含它们。

答案 2 :(得分:0)

我的答案来晚了,但添加了其他人没有的答案,所以去了...

简短的回答:尚不清楚标准是否允许标准C ++标头包含标准C标头。

其他答案已正确观察到C ++标准

  • 允许使用标准的C ++标头
  • 包括一个标准的C ++头文件。

尚不清楚的是标准C标头是否是标准C ++标头。我可以通过两种方式给出证据。

为什么C标头确实是C ++标头

在具有GNU标准C库2.24的GCC 6.24上,以下测试无法编译。

#include <iostream>

namespace {
    const int printf {42};
}

int main()
{
    std::cout << printf << "\n";
    return 0;
}

尽管测试缺少明确的#include <cstdio>,但编译器仍抱怨“对'printf'的引用不明确”。

主要编译器和标准库(例如GCC和GNU)的开发人员的判断几乎不容忽视。

其他答案也提供了其他原因,我无需在这里重复。

为什么C标头不是C ++标头

C ++ 17标准(草稿here)脚注166内容如下:

  

[C]用于C库工具的C ++头可以在全局名称空间中定义名称。

如果C头是C ++头,那么编写这样的脚注将是一种奇怪的方式,不是吗?取而代之的是,人们希望脚注以“ C库工具的非<*.h> C ++头文件……”开头。

最后的观察结果尚无定论,但在[res.on.headers]中,标准也显示为:

  

C标准库标头应仅包括其相应的C ++标准库标头。...

再说一次,如果在写单词的人的估计中C头是C ++头,那么写它们似乎是一种奇怪的方式。

结论:模棱两可

不幸的是,像其他答复者一样,我无法以一种或另一种标准方式找到明确的答案。与其他答复者不同,我得出的结论是答案仍然模棱两可。该标准的相关部分包括[内容],[标题标题]和[de.c.header]。

意见

如果您想知道在我看来哪种选择占优势,那么我倾向于不同意其他答案。由于上述原因,我倾向于说标准不允许标准C ++头包含标准C头。这种包容在任何程度上都与普通C ++的使用相矛盾,因为这种包容使得匿名全局名称空间更难使用。 [在测试中将printf更改为foo,然后询问如果将来的标准C库添加函数foo()会发生什么。这样的实验说明了麻烦。]

另一方面,与一个人的工具链搏斗是毫无意义的,不是吗?在澄清将来的C ++版本之前,我的意思是避免在包含标准库头的源文件中使用匿名全局命名空间。

我怀疑,由于该标准已弃用了使用标准C标头的旧样式,因此标准委员会可能在考虑如何同时修补旧样式的问题时不会太费劲。也许C ++ 20模块将提供一个简洁的解决方案。我们将会看到。