Do I need an extern "C" block to include standard POSIX C headers?
The system C headers usually already include a extern "C"
block, guarded by #ifdef __cplusplus
. This way the functions automatically get declared as extern "C"
when compiled as C++ and you don't need to do that manually.
For example on my system unistd.h
and fcntl.h
start with __BEGIN_DECLS
and end with __END_DECLS
, which are macros defined in sys/cdefs.h
:
/* C++ needs to know that types and declarations are C, not C++. */
#ifdef __cplusplus
# define __BEGIN_DECLS extern "C" {
# define __END_DECLS }
#else
# define __BEGIN_DECLS
# define __END_DECLS
#endif
The behavior of <fcntl.h>
and <unistd.h>
in C++ is not specified by the standard (because they are also not part of the C89 standard). That said, I have never seen a platform where they (a) exist and (b) actually need to be wrapped in an extern "C"
block.
The behavior of <stdio.h>
, <math.h>
, and the other standard C headers is specified by section D.5 of the C++03 standard. They do not require an extern "C"
wrapper block, and they dump their symbols into the global namespace. However, everything in Annex D is "deprecated".
The canonical C++ form of those headers is <cstdio>
, <cmath>
, etc., and they are specified by section 17.4.1.2 (3) of the C++ standard, which says:
<cassert> <ciso646> <csetjmp> <cstdio> <ctime> <cctype> <climits>
<csignal> <cstdlib> <cwchar> <cerrno> <clocale> <cstdarg> <cstring>
<cwctype>
Except as noted in clauses 18 through 27, the contents of each header cname shall be the same as that of the corresponding header name.h, as specified in ISO/IEC 9899:1990 Programming Languages C (Clause 7), or ISO/IEC:1990 Programming Languages—C AMENDMENT 1: C Integrity, (Clause 7), as appropriate, as if by inclusion. In the C++ Standard Library, however, the declarations and definitions (except for names which are defined as macros in C) are within namespace scope (3.3.5) of the namespace std.
So the standard, non-deprecated, canonical way to use (e.g.) printf
in C++ is to #include <cstdio>
and then invoke std::printf
.