If a variable is declared somewhere without extern "C" (e.g. in a header file) and afterwards defined with extern "C", then the Visual C++ compiler compiles it with C++ linkage without further notice:
extern IntStruct ifcStruct;
extern int ifcVar;
/* ... */
extern "C"
{
IntStruct ifcStruct;
int ifcVar = 0;
}
dumpbin /symbols test.obj shows C++ symbols with mangled names:
00C 00000000 SECT4 notype External | ?ifcStruct@@3UIntStruct@@A (struct IntStruct ifcStruct)
00D 00000008 SECT4 notype External | ?ifcVar@@3HA (int ifcVar)
However, when a function is declared without and then defined with extern "C"
extern void ifcf ();
/* ... */
extern "C" void ifcf () {}
then the Visual C++ compiler gives a distinct error message:
test.cpp(20): error C2732: linkage specification contradicts earlier specification for 'ifcf'
test.cpp(20): note: see declaration of 'ifcf'
Is there an explaination for this difference that arises from the standard?
It makes no difference whether the extern "C" is used with or without {...}.
And it makes no difference whether the function declaration is done with or without extern.
The variable declaration needs the extern - otherwise it is "redefinition". However, there is no difference whether the extern is specified at the declaration, or at the definition, or both. In all cases the first occurence defines the language linkage.
edit: As Karen stated, the behavior on functions is described by Microsoft,
as well as on cppreference.com:
A function can be re-declared without a linkage specification after it was declared with a language specification, the second declaration will reuse the first language linkage. The opposite is not true: if the first declaration has no language linkage, it is assumed "C++", and redeclaring with another language is an error.
From here
As you can see, according to the quote, the declaration of function with
extern "C"specifier should appear first appear first.However, the situation is different with
extern "C" {...}The first tells the compiler that if there is a name or symbol with external linkage inside the blocks, use C naming, otherwise use C++ name mangling. But as far as you have defined the names inside
extern "C" {...}they have internal linkage, hence no C naming is used. It can be seen from 9.11.5