简体   繁体   English

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

[英]Can a C++ standard library header include a C standard header?

I can only find in the standard draft N4582 that 我只能在标准草案N4582中找到

[res.on.headers/1] A C++ header may include other C++ headers. [res.on.headers / 1] C ++标头可能包含其他C ++标头。

It seems not to specify that whether a C++ header can include a C standard header. 似乎没有指定C ++标头是否可以包含C标准标头。

If it is permitted, is it unsafe to use a global name defined in a C standard header even if this header is not included (since the program may implicitly include the header through some C++ standard header)? 如果允许,即使不包含此标头,使用C标准头中定义的全局名称是否不安全(因为程序可能通过某些C ++标准头隐式包含头)?

Section D.3 C standard library headers of the C++ standard makes 26 C standard headers part of C++. D.3节C ++标准的C标准库头使26 C标准头部成为C ++的一部分。 Thus those are part of C++. 因此,这些是C ++的一部分。 Also many other C headers adhere to the shared subset of the languages (probably by #ifdef ing some things out) making them both, valid C and C++ headers. 此外,许多其他C标头都遵循语言的共享子集(可能通过#ifdef ing some #ifdef ),使它们成为有效的C和C ++标头。

For the purpose of the question you follow up with (name conflicts), yes, it certainly can. 对于你跟进的问题(名称冲突),是的,它当然可以。 The reason is that the C++ standard library includes the <c:::> C++ headers for the C standard library contents, and the standard explicitly allows these to provide the names in the global namespace as well (in addition to mandatorily providing them in ::std ). 原因是C ++标准库包含C标准库内容的<c:::> C ++标头,标准明确允许它们在全局命名空间中提供名称(除了强制提供它们之外::std )。

Further, based on Annex D [depr] of the C++ standard, the C standard library headers (the <:::.h> versions) are also part of the C++ standard library (albeit deprecated). 此外,根据C ++标准的附录D [depr],C标准库头文件( <:::.h>版本)也是C ++标准库的一部分(尽管已弃用)。 This means [res.on.headers]/1 allows C++ headers to include them. 这意味着[res.on.headers] / 1允许C ++标头包含它们。

My answer comes late but adds something the others do not, so here goes.... 我的答案来得晚,但增加了其他人没有的东西,所以这里......

Short answer: whether the standard allows a standard C++ header to include a standard C header remains unclear. 简短回答:标准是否允许标准C ++标头包含标准C标头仍然不清楚。

Other answers have correctly observed that the C++ standard 其他答案已正确观察到C ++标准

  • allows a standard C++ header 允许标准的C ++标头
  • to include a standard C++ header. 包括标准C ++标头。

What remains unclear is whether a standard C header is a standard C++ header. 目前尚不清楚的是标准C头是否是标准C ++头。 I can give evidence both ways. 我可以两种方式提供证据。

Why a C header is indeed a C++ header 为什么C头确实是C ++头

On GCC 6.24 with GNU's standard C library 2.24, the following test fails to compile. 在带有GNU标准C库2.24的GCC 6.24上,以下测试无法编译。

#include <iostream>

namespace {
    const int printf {42};
}

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

The compiler complains, "reference to 'printf' is ambiguous," despite that the test lacks an explicit #include <cstdio> . 编译器抱怨说,“对'printf'的引用是模棱两可的,”尽管测试缺少一个明确的#include <cstdio>

The judgment of the developers of a major compiler and standard library like GCC and GNU is hardly to be ignored. 主要编译器和标准库(如GCC和GNU)的开发人员的判断很难被忽略。

Other answers have given further reasons I need not reprise here. 其他答案进一步说明了我不需要在此重复的原因。

Why a C header is not a C++ header 为什么C头不是C ++头

The C++17 standard (draft here ), footnote 166, reads: 在C ++ 17标准(草案这里 ),脚注166,显示如下:

[T]he C++ headers for C library facilities may ... define names within the global namespace. [C] C库设施的C ++头文件可以...定义全局命名空间中的名称。

If C headers were C++ headers, then that would be an odd way to have written such a footnote, would it not? 如果C标题是C ++标题,那么编写这样一个脚注是一种奇怪的方式,不是吗? One would instead have expected the footnote to begin with words like, "The non- <*.h> C++ headers for C library facilities ..." 相反,我们可以预期脚注会以“C库设施的非<*.h> C ++标题......”开头<*.h>

The last observation is inconclusive but, in [res.on.headers], the standard also reads: 最后一个观察结果尚无定论,但在[res.on.headers]中,该标准还包括:

The C standard library headers shall include only their corresponding C++ standard library header.... C标准库头只应包含其对应的C ++标准库头....

Again, if C headers were C++ headers in the estimation of the person that wrote the words, then that would seem an odd way to have written them. 同样,如果在编写单词的人的估计中C头是C ++头,那么编写它们似乎是一种奇怪的方式。

Conclusion: ambiguous 结论:含糊不清

Unfortunately, like other answerers, I cannot find a clear answer in the standard one way or the other. 不幸的是,像其他回答者一样,我无法在标准的某种方式中找到明确的答案。 Unlike other answerers, I would conclude that the answer remains ambiguous. 与其他回答者不同,我会得出结论,答案仍然含糊不清。 Relevant sections in the standard include [contents], [res.on.headers] and [depr.c.headers]. 标准中的相关部分包括[contents],[res.on.headers]和[depr.c.headers]。

Opinion 意见

If you wish to know which alternative carries the preponderance of the evidence in my opinion, then I would tend to disagree with the other answers. 如果您想知道哪种替代方案在我看来具有优势证据,那么我倾向于不同意其他答案。 For the reasons cited, I would tend to say that the standard did not allow a standard C++ header to include a standard C header. 由于引用的原因,我倾向于说标准不允许标准C ++头包含标准C头。 Such inclusion contradicts ordinary C++ usage, at any rate, insofar as such inclusion makes anonymous global namespaces harder to use. 无论如何,这种包含与普通的C ++使用相矛盾,只要这种包含使得匿名全局命名空间更难以使用。 [Change printf to foo in my test and then ask what would happen if a future standard C library added a function foo() . [在我的测试中将printf更改为foo ,然后询问如果未来的标准C库添加了函数foo()会发生什么。 Such an experiment illustrates the trouble.] 这样的实验说明了麻烦。]

On the other hand, fighting one's toolchain is fairly pointless, isn't it? 另一方面,打一个人的工具链是没有意义的,不是吗? Until a future version of C++ clarifies, I for one mean to avoid anonymous global namespaces in source files that include standard library headers. 在C ++的未来版本澄清之前,我的意思是避免在包含标准库头的源文件中使用匿名全局命名空间。

I suspect that, since the standard has deprecated the old styles by which standard C headers are used, the standards committee might not be thinking too hard about how to patch problems with the old style in the meantime. 我怀疑,由于标准已经弃用了使用标准C头的旧样式,标准委员会可能不会过于考虑如何在此期间修补旧样式的问题。 Maybe C++20 modules will afford a neat solution. 也许C ++ 20模块可以提供一个简洁的解决方案。 We shall see. 我们会看到。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM