Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Do I need an extern "C" block to include standard POSIX C headers?

Tags:

c++

posix-api

Do I need an extern "C" {} block to include standard C headers in a C++ program. Only consider standard C headers which do not have counterparts in C++.

For example:

extern "C" {
 #include <fcntl.h>
 #include <unistd.h>
}
like image 722
Martin Avatar asked Nov 10 '11 22:11

Martin


People also ask

Is extern C necessary?

the extern keyword is used to extend the visibility of variables/functions. Since functions are visible throughout the program by default, the use of extern is not needed in function declarations or definitions. Its use is implicit.

Should externs be in header files?

All variables and functions in header files should be extern. Separate header files should be used for variables and functions. Use a C code file to declare the variables and functions and use this in end user code. Extern must be used instead of using global variables.

Is it necessary to include header file in C?

In C program should necessarily contain the header file which stands for standard input and output used to take input with the help of scanf() and printf() function respectively.

How can I include a standard C++ header file in my C code?

If you are including a C header file that isn't provided by the system, you may need to wrap the #include line in an extern "C" { /*... */ } construct. This tells the C++ compiler that the functions declared in the header file are C functions.


2 Answers

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
like image 131
sth Avatar answered Sep 23 '22 12:09

sth


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.

like image 32
Nemo Avatar answered Sep 22 '22 12:09

Nemo