简体   繁体   中英

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

I can only find in the standard draft N4582 that

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

It seems not to specify that whether a C++ header can include a C standard header.

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)?

Section D.3 C standard library headers of the C++ standard makes 26 C standard headers part of C++. Thus those are part of 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.

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 ).

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). This means [res.on.headers]/1 allows C++ headers to include them.

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.

Other answers have correctly observed that the C++ standard

  • allows a standard C++ header
  • to include a standard C++ header.

What remains unclear is whether a standard C header is a standard C++ header. I can give evidence both ways.

Why a C header is indeed a C++ header

On GCC 6.24 with GNU's standard C library 2.24, the following test fails to compile.

#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> .

The judgment of the developers of a major compiler and standard library like GCC and GNU is hardly to be ignored.

Other answers have given further reasons I need not reprise here.

Why a C header is not a C++ header

The C++17 standard (draft here ), footnote 166, reads:

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

If C headers were C++ headers, then that would be an odd way to have written such a footnote, would it not? One would instead have expected the footnote to begin with words like, "The non- <*.h> C++ headers for C library facilities ..."

The last observation is inconclusive but, in [res.on.headers], the standard also reads:

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

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.

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].

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. Such inclusion contradicts ordinary C++ usage, at any rate, insofar as such inclusion makes anonymous global namespaces harder to use. [Change printf to foo in my test and then ask what would happen if a future standard C library added a function 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.

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. Maybe C++20 modules will afford a neat solution. We shall see.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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