The ISO C++ standard specifies that the macro "__cplusplus" is #defined whenever compiling C++ code.

Most implementations #define various constants which specify parts of their configuration. This is useful for conditional compilation. __cplusplus is particularly useful for mixed-language C/C++ programming. Both ISO C and ISO C++ leave all identifiers beginning with two underscores "__" for use by the implementation. So existing C and C++ programs should not be using this identifier (and, indeed, it is hard to imagine why anyone would want to use this identifier by themselves...). Of course, an existing ISO C implementation might choose to #define this constant, but that too appears somewhat unlikely.

So __cplusplus is a good choice of identifier. But why use it? After all, when I write code I know what language I'm writing!

Almost. In mixed-language programming, header files may very well be #included from both C and C++ filestranslation units (and that's the last stupid joke about translation units, for this writeup at least). And C++ requires different declarations for this case.

The extern "C" C++ linkage specifier must be used to declare any function with C linkage. So if we want to declare printf in C++, we'd have to say

extern "C" int printf(const char *fmt, ...);
Of course, if this was actually written in stdio.h, the C compiler would choke on it -- extern "C" is not part of C! One solution would be to use 2 different header files for C and C++. We could even configure our compiler to search different directories for these header files, and give them the same name. But that's clumsy and annoying.

Instead, we write a header file that looks a bit like this:

#ifdef __cplusplus
extern "C" {
#endif
/* ... */
int printf(const char *fmt, ...);
int fprintf(FILE *f, const char *fmt, ...);
/* ... */
#ifdef __cplusplus
}
#endif
We can now #include this file both in a C++ source file and in a C source file. When compiling the first, the C++ compiler will #define __cplusplus, so it will see the declarations enclosed inside extern "C". And when compiling the second, the C compiler won't #define __cplusplus, so it will see the declarations unadorned.

Another similar trick is to use a macro before each declaration:

#ifdef __cplusplus
#define EXTERNC extern "C"
#else
#define EXTERNC
#endif
/* ... */
EXTERNC int printf(const char *fmt, ...);
EXTERNC int fprintf(FILE *f, const char *fmt, ...);
/* ... */
#undef EXTERNC
This works just as well, but is perhaps a bit harder to maintain. Use whichever you prefer, I guess.

The __cplusplus trick is also useful when exporting functions defined in C++ to callers written in C. For example, suppose some stdio.h implementation was written on top of iostreams. We could use a single #include for both languages:

#ifdef __cplusplus
class std::ostream {
  // ...
};
// definition of various streams go here
typedef std::ostream FILE;
extern "C" {       // Shared declarations come later
#else              /* Declarations for C: make "FILE*" work */
typedef struct __std_ostream FILE;
#endif
int fprintf(FILE *f, const char *fmt, ...);
FILE* fopen(const char *fname, const char *mode);
/* ... */
#ifdef __cplusplus
}                  // Close extern "C"
#endif
C code #including this header will receive a completely abstract FILE pointer -- the struct has no definition. Both C and C++ code #including the header will see the stdio.h declarations. In addition, C++ code will also know about the class std::ostream, and be able to use it. C can't know about this class -- it has no class -- so we do well to hide its existence from the C compiler.

Log in or registerto write something here or to contact authors.