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

Can a C++ standard library header include a C standard header?

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

[res.on.headers/1] A C++ header may include other C++ headers.

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

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

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

就您跟进的问题(名称冲突)而言,是的,当然可以。原因是 C++ 标准库包括 <c:::> C++ headers 用于 C 标准库内容,标准明确允许这些也提供全局名称空间中的名称(除了强制提供他们在 ::std).

此外,基于 C++ 标准的附件 D [depr],C 标准库 headers(<:::.h> 版本)也是 C++ 标准库的一部分(尽管已弃用)。这意味着 [res.on.headers]/1 允许 C++ headers 包含它们。

我的回答来晚了,但添加了其他人没有的内容,所以这里....

简短回答:标准是否允许标准 C++ header 包含标准 C header 仍不清楚。

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

  • 允许标准 C++ header
  • 包括标准 C++ header。

尚不清楚的是标准 C header 是否是标准 C++ header。 我可以提供两种方式的证据。

为什么 C header 确实是 C++ header

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

#include <iostream>

namespace {
    const int printf {42};
}

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

编译器抱怨,"reference to ‘printf’ is ambiguous," 尽管测试缺少明确的 #include <cstdio>

GCC、GNU等主流编译器和标准库开发者的评价不容忽视

其他答案已经给出了进一步的理由,我不需要在这里重复。

为什么 C header 不是 C++ header

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

[T]he C++ headers for C library facilities may ... define names within the global namespace.

如果 C headers 是 C++ headers,那么写这样一个脚注将是一种奇怪的方式,不是吗?相反,人们会期望脚注以 "The non-<*.h> C++ headers for C library facilities ..."

这样的词开头

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

The C standard library headers shall include only their corresponding C++ standard library header....

同样,如果 C headers 是 C++ headers 在写这些词的人的估计中,那么写它们的方式似乎很奇怪。

结论:模棱两可

不幸的是,和其他回答者一样,我无法以标准的方式找到明确的答案。与其他回答者不同,我认为答案仍然模棱两可。标准中的相关部分包括 [目录]、[res.on.headers] 和 [depr.c.headers].

意见

如果您想知道在我看来哪个选项具有优势证据,那么我倾向于不同意其他答案。由于引用的原因,我倾向于说该标准不允许标准 C++ header 包含标准 C header。无论如何,这种包含与普通的 C++ 用法相矛盾,因为这种包含使匿名全局名称空间更难使用。 [在我的测试中将 printf 更改为 foo 然后询问如果未来的标准 C 库添加一个函数 foo() 会发生什么。这样的实验就说明了问题。]

另一方面,与一个人的工具链作斗争是毫无意义的,不是吗?在 C++ 的未来版本澄清之前,我的意思是避免在包含标准库 headers.

的源文件中使用匿名全局名称空间

我怀疑,由于该标准已经弃用了使用标准 C header 的旧样式,因此标准委员会可能不会认真考虑如何修补旧样式中的问题与此同时。也许 C++20 模块会提供一个简洁的解决方案。我们拭目以待。