External linkage and »extern "C"« block

c, c++

Solution

The inner `extern` means what expected: "the symbol is defined somewhere else, it has external linkage, don't allocate space for it in this unit (unless defined here as well)".

The outer `extern "C" { ... }` has maybe a bit misleading syntax, it only tells the compiler "if you are creating names of any symbols with external linkage inside this block, use traditional C naming (C language linkage) instead of C++ name mangling (C++ language linkage) for them". But it does not specify that all things inside the block are "defined somewhere else" (have external linkage) -- they are still declared with the default internal linkage. That's why you need the inner `extern` as well.

The one-line variant `extern "C" <variable declaration>` is just a shorthand, as you probably want to define an external variable if you care about its cross-unit symbol name.

(As a side-note, I would include `i.h` also in `i.cpp`, that way I wouldn't have to remember to mess with `extern "C"` any more in the implementation.)

Problem

I have an `int ID`, which I want to define in C++ and make available for C linkage (contrived case for the sake of simplicity): ``` /* i.h */ #ifdef __cplusplus extern "C" { #endif extern int ID; #ifdef __cplusplus } #endif ``` Here's a C and a C++ program using the `int`: ``` /* m.cpp */ #include "i.h" #include <iostream> int main() { std::cout << ID << std::endl; } /* m.c */ #include "i.h" #include <stdio.h> int main() { printf("%d\n", ID); } ``` Now what I'm wondering is the syntax of `extern "C"` and/or `extern`. Here's how `int ID` can and cannot be defined: ``` /* i.cpp */ // const int ID = 88; // no C linkage, obviously, LNK2019/1120 // extern "C" const int ID = 88; // provides C linkage // extern "C" { const int ID = 88; } // no C linkage, surprisingly, LNK2019/1120 // extern "C" { extern const int ID = 88; } // C linkage restored ``` Compiling: ``` cl /nologo /W4 m.cpp i.cpp /MD /EHsc cl /nologo /W4 m.c i.cpp /MD ``` What I don't understand is the syntax when `extern "C"` is used with a `{block}`. I have to repeat the `extern`, whereas with the blockless form of `extern "C"` I do not. Is this just a syntax quirk or is there more to it? I stumbled upon this issue on page 98 of Inside COM by Dale Rogerson. There is a code listing with the nested `extern` and a comment intended to clarify (but which I don't understand): ``` #include <objbase.h> extern "C"{ extern const IID IID_IX = {0x32bb8320, 0x41b, 0x11cf, ...}; // The extern is required to allocate memory for C++ constants. } ``` Can anyone explain the internal `extern`?

Original source