extern and extern “C” for variables

2019-04-08 18:43发布

问题:

I'm writing a C++ shared library for a C program to use. However, I have a question about extern and extern "C".

Consider the following code

My header file is like this:

#ifdef __cplusplus      
     extern "C" int global;
     extern "C" int addnumbers(int a, int b); 
 #else
      extern int global;
 #endif

This works perfectly fine; I just have to declare

int global;

in either my .cpp or my .c file. However, what I don't understand is:

What is the difference between extern "C" and extern here? I tried commenting out extern "C" int global and it works! Why?

I know that extern "C" is used for making C linkage. That's why I have extern "C" int addnumbers(int,int). In other words, if I want to write a C++ function that is to be used in a C program, I write extern "C". Now, what about global variables - the situation is different here I guess? I want the C program to use a C++ variable named global, but I can use extern not extern "C". Why is that? This is not intuitive to me.

Comment: I don't think this is a duplicate, because I'm asking what the difference is when you use it for variables versus functions.

回答1:

By attaching extern "C" to your C++ declarations (objects and functions alike) you give them "C linkage" - make them accessible from C code. If you omit this "language linkage" specification, the compiler doesn't do any effort to do proper linkage. In the case of functions, this results in failed linkage, because of mangling. In the case of global variables, everything might work fine, because variables don't need mangling.

However, on my system (MS Visual Studio), linkage between C and C++ doesn't work if I "forget" to specify the extern "C" linkage specification in the C++ header file. Example error message:

error LNK2001: unresolved external symbol "int global" (?_global)

While, when I examine a compiled C++ source code that contains the definition of global with the dumpbin utility, I see

00B 00000014 SECT4  notype       External     | ?global@@3HA (int global)

So MS Visual Studio mangles the names of global variables, unless they have C linkage - this makes C linkage specifications mandatory.


In addition, consider the following example:

namespace example {
    int global;
}

If the global variable is inside a namespace, C code will not get access to it. In this case, all compilers will require the proper linkage specification on the C++ declaration:

namespace example {
    extern "C" int global;
}

Conclusion:

Use extern "C" when you want C linkage - doesn't matter if it's a function or a global variable. If it's a global variable, it may work regardless, but it's not guaranteed (and may be dangerous).



回答2:

extern simply tells the compiler that the next variable(global) may not have been declared yet, but it is declared as global in a different translation unit, and during the linking stage the symbol "global" will be associated with an area in the memory.

while extern "C" is, as a few people commented, is used to solve the issue of name mangling in C++, this function will be known as addnumbers_i_i (or something similar) by the linker, while in c its symbol is addnumbers



回答3:

"C++ has a special keyword to declare a function with C bindings: extern "C". A function declared as extern "C" uses the function name as symbol name, just as a C function. For that reason, only non-member functions can be declared as extern "C", and they cannot be overloaded."

There is no standard in C++ for function names generated by compiler. Keyword extern "C" instructs compiler to generate function name in C standard.



回答4:

I find that extern "C" is used to make the C++ function compiled in C standard and it don't do with variables, for the solutions of function name in C and C++ are different. Such as "void foo( int x, int y )", C compiler will translate it into "_foo", while C++ compiler will translate it into "_foo_int_int".