When to use extern in C++
This comes in useful when you have global variables. You declare the existence of global variables in a header, so that each source file that includes the header knows about it, but you only need to “define” it once in one of your source files.
To clarify, using extern int x;
tells the compiler that an object of type int
called x
exists somewhere. It's not the compilers job to know where it exists, it just needs to know the type and name so it knows how to use it. Once all of the source files have been compiled, the linker will resolve all of the references of x
to the one definition that it finds in one of the compiled source files. For it to work, the definition of the x
variable needs to have what's called “external linkage”, which basically means that it needs to be declared outside of a function (at what's usually called “the file scope”) and without the static
keyword.
header:
#ifndef HEADER_H
#define HEADER_H
// any source file that includes this will be able to use "global_x"
extern int global_x;
void print_global_x();
#endif
source 1:
#include "header.h"
// since global_x still needs to be defined somewhere,
// we define it (for example) in this source file
int global_x;
int main()
{
//set global_x here:
global_x = 5;
print_global_x();
}
source 2:
#include <iostream>
#include "header.h"
void print_global_x()
{
//print global_x here:
std::cout << global_x << std::endl;
}
What is the effect of extern C in C++?
extern "C"
makes a function-name in C++ have C linkage (compiler does not mangle the name) so that client C code can link to (use) your function using a C compatible header file that contains just the declaration of your function. Your function definition is contained in a binary format (that was compiled by your C++ compiler) that the client C linker will then link to using the C name.
Since C++ has overloading of function names and C does not, the C++ compiler cannot just use the function name as a unique id to link to, so it mangles the name by adding information about the arguments. A C compiler does not need to mangle the name since you can not overload function names in C. When you state that a function has extern "C"
linkage in C++, the C++ compiler does not add argument/parameter type information to the name used for linkage.
Just so you know, you can specify extern "C"
linkage to each individual declaration/definition explicitly or use a block to group a sequence of declarations/definitions to have a certain linkage:
extern "C" void foo(int);
extern "C"
{
void g(char);
int i;
}
If you care about the technicalities, they are listed in section 7.5 of the C++03 standard, here is a brief summary (with emphasis on extern "C"
):
extern "C"
is a linkage-specification- Every compiler is required to provide "C" linkage
- A linkage specification shall occur only in namespace scope
All function types, function names and variable names have a language linkageSee Richard's Comment: Only function names and variable names with external linkage have a language linkage- Two function types with distinct language linkages are distinct types even if otherwise identical
- Linkage specs nest, inner one determines the final linkage
extern "C"
is ignored for class members- At most one function with a particular name can have "C" linkage (regardless of namespace)
See Richard's comment:extern "C"
forces a function to have external linkage (cannot make it static)static
insideextern "C"
is valid; an entity so declared has internal linkage, and so does not have a language linkage- Linkage from C++ to objects defined in other languages and to objects defined in C++ from other languages is implementation-defined and language-dependent. Only where the object layout strategies of two language implementations are similar enough can such linkage be achieved
When to use extern C in C++? [duplicate]
extern "C" makes names not mangled.
It used when:
We need to use some C library in C++
extern "C" int foo(int);
We need export some C++ code to C
extern "C" int foo(int) { something; }
We need an ability to resolve symbol in shared library -- so we need to get rid mangling
extern "C" int foo(int) { something; }
///
typedef int (*foo_type)(int);
foo_type f = (foo_type)dlsym(handle,"foo")
Why use the extern keyword in header in C? [duplicate]
extern float kFloat;
declares kFloat
without defining it.
but:
float kFloat;
also declares kFloat
but is a tentative definition of kFloat
.
Adding extern
just suppresses the tentative definition. In a header file you only want declarations, not definitions.
If the tentative definition is included in several source files, you will end up having multiple definitions of the same object which is undefined behavior in C.
How to correctly use the extern keyword in C
extern
changes the linkage. With the keyword, the function / variable is assumed to be available somewhere else and the resolving is deferred to the linker.
There's a difference between extern
on functions and on variables.
For variables it doesn't instantiate the variable itself, i.e. doesn't allocate any memory. This needs to be done somewhere else. Thus it's important if you want to import the variable from somewhere else.
For functions, this only tells the compiler that linkage is extern. As this is the default (you use the keyword static
to indicate that a function is not bound using extern linkage) you don't need to use it explicitly.
Related Topics
What Is a Lambda Expression in C++11
When to Use Virtual Destructors
How to Print Bytes as Hexadecimal
C++11 Std::To_String(Double) - No Trailing Zeros
Combining Multiple for Loops into Single Iterator
Why Can Templates Only Be Implemented in the Header File
How to Peek At the Next Element in a Range-For Loop
While Writting Unittests for a Function, Should I Mock the Internal Function Calls Made
What Is the Strict Aliasing Rule
How to Properly Add Include Directories With Cmake
What Are Copy Elision and Return Value Optimization
Difference Between Function Overloading and Template Function Which Is More Appropriate
Iterator Invalidation Rules For C++ Containers
Sorting Characters in a String First by Frequency and Then Alphabetically
How to Expand a Tuple into Variadic Template Function'S Arguments
Parsing a Comma-Delimited Std::String
What Will Happen When I Call a Member Function on a Null Object Pointer