There are times when an include file has to generate different output from the preprocessor depending on whether the compiler is a C compiler or a C++ compiler due to language differences.
For example a function or other external is defined in a C source file but is used in a C++ source file. Since C++ uses name mangling (or name decoration) in order to generate unique function names based on function argument types, a C function declaration used in a C++ source file will cause link errors. The C++ compiler will modify the specified external name for the compiler output using the name mangling rules for C++. The result is link errors due to externals not found when the C++ compiler output is linked with the C compiler output.
Since C compilers do not do name mangling but C++ compilers do for all external labels (function names or variable names) generated by the C++ compiler, a predefined preprocessor macro, __cplusplus
, was introduced to allow for compiler detection.
In order to work around this problem of incompatible compiler output for external names between C and C++, the macro __cplusplus
is defined in the C++ Preprocessor and is not defined in the C Preprocessor. This macro name can be used with the conditional preprocessor #ifdef
directive or #if
with the defined()
operator to tell whether a source code or include file is being compiled as C++ or C.
#ifdef __cplusplus
printf("C++\n");
#else
printf("C\n");
#endif
Or you could use
#if defined(__cplusplus)
printf("C++\n");
#else
printf("C\n");
#endif
In order to specify the correct function name of a function from a C source file compiled with the C compiler that is being used in a C++ source file you could check for the __cplusplus
defined constant in order to cause the extern "C" { /* ... */ };
to be used to declare C externals when the header file is included in a C++ source file. However when compiled with a C compiler, the extern "C" { */ ... */ };
is not used. This conditional compilation is needed because extern "C" { /* ... */ };
is valid in C++ but not in C.
#ifdef __cplusplus
// if we are being compiled with a C++ compiler then declare the
// following functions as C functions to prevent name mangling.
extern "C" {
#endif
// exported C function list.
int foo (void);
#ifdef __cplusplus
// if this is a C++ compiler, we need to close off the extern declaration.
};
#endif