32

I'm taking a programming languages course and we're talking about the extern "C" declaration.

How does this declaration work at a deeper level other than "it interfaces C and C++"? How does this affect the bindings that take place in the program as well?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
samoz
  • 56,849
  • 55
  • 141
  • 195

9 Answers9

54

extern "C" is used to ensure that the symbols following are not mangled (decorated).


Example:

Let's say we have the following code in a file called test.cpp:

extern "C" {
  int foo() {
    return 1;
  }
}

int bar() {
  return 1;
}

If you run gcc -c test.cpp -o test.o

Take a look at the symbols names:

00000010 T _Z3barv

00000000 T foo

foo() keeps its name.

Bertrand Marron
  • 21,501
  • 8
  • 58
  • 94
  • 8
    Also that functions use the C calling convention, if it differs from the C++ calling convention. Which it probably doesn't, for C++ functions which take only types from C as parameters, but with `extern "C"` it definitely doesn't. – Steve Jessop Mar 08 '10 at 17:59
  • What call did you use to get the symbol names there? – meawoppl Apr 01 '14 at 04:45
28

Let's look at a typical function that can compile in both C and C++:

int Add (int a, int b)
{
    return a+b;
}

Now in C the function is called "_Add" internally. Whereas the C++ function is called something completely different internally using a system called name-mangling. Its basically a way to name a function so that the same function with different parameters has a different internal name.

So if Add() is defined in add.c, and you have the prototype in add.h you will get a problem if you try to include add.h in a C++ file. Because the C++ code is looking for a function with a name different to the one in add.c you will get a linker error. To get around that problem you must include add.c by this method:

extern "C"
{
#include "add.h"
}

Now the C++ code will link with _Add instead of the C++ name mangled version.

That's one of the uses of the expression. Bottom line, if you need to compile code that is strictly C in a C++ program (via an include statement or some other means) you need to wrap it with a extern "C" { ... } declaration.

Cthutu
  • 8,713
  • 7
  • 33
  • 49
10

When you flag a block of code with extern "C", you're telling the system to use C style linkage.

This, mainly, affects the way the linker mangles the names. Instead of using C++ style name mangling (which is more complex to support operator overloads), you get the standard C-style naming out of the linker.

Reed Copsey
  • 554,122
  • 78
  • 1,158
  • 1,373
  • 1
    I don't think you should be suggesting that a **method** could be flagged with `extern "C"`. Single functions or multiple functions are OK. – quamrana Mar 08 '10 at 18:09
  • @Reed: err.. I've just realised that you talk of linkage and linkers. It affects the compiler naming, which only indirectly affects the linker. – quamrana Mar 08 '10 at 18:36
  • @quamrana: Read http://msdn.microsoft.com/en-us/library/0603949d(VS.80).aspx - It does directly affect, and is used by, the linker. The compiler mangles the name, but the linker is the one that USES the naming - extern "C" is there in order to allow the linker to work properly, whether in C or C++, since the linker is the one that has to determine how to map between translation units. – Reed Copsey Mar 08 '10 at 18:39
6

It should be noted that extern "C" also modifies the types of functions. It does not only modify things on lower levels:

extern "C" typedef void (*function_ptr_t)();

void foo();

int main() { function_ptr_t fptr = &foo; } // error!

The type of &foo does not equal the type that the typedef designates (although the code is accepted by some, but not all compilers).

Johannes Schaub - litb
  • 496,577
  • 130
  • 894
  • 1,212
5

In C++ the name/symbol of the functions are actually renamed to something else such that different classes/namespaces can have functions of same signatures. In C, the functions are all globally defined and no such customized renaming process is needed.

To make C++ and C talk with each other, "extern C" instructs the compiler not to use the C convention.

gilbertc
  • 1,049
  • 1
  • 10
  • 19
  • 4
    for more on name mangling, there's Wikipedia: http://en.wikipedia.org/wiki/Name_mangling – jakebman Mar 08 '10 at 17:59
  • 1
    ' "extern C" instructs the compiler not to use the C convention' No that's backwards. "extern C" instructs a C++ compiler TO use the C convention for naming symbols. – JonN Nov 02 '17 at 23:48
5

extern C affects name mangling by the C++ compiler. Its a way of getting the C++ compiler to not mangle names, or rather to mangle them in the same way that a C compiler would. This is the way it interfaces C and C++.

As an example:

extern "C" void foo(int i);

will allow the function to be implemented in a C module, but allow it to be called from a C++ module.

The trouble comes when trying to get a C module to call a C++ function (obviously C can't use C++ classes) defined in a C++ module. The C compiler doesn't like extern "C".

So you need to use this:

#ifdef __cplusplus
extern "C" {
#endif

void foo(int i);

#ifdef __cplusplus
}
#endif

Now when this appears in a header file, both the C and C++ compilers will be happy with the declaration and it could now be defined in either a C or C++ module, and can be called by both C and C++ code.

quamrana
  • 37,849
  • 12
  • 53
  • 71
4

extern "C" denotes that the enclosed code uses C-style linking and name mangling. C++ uses a more complex name mangling format. Here's an example:

http://en.wikipedia.org/wiki/Name_mangling

int example(int alpha, char beta);

in C: _example

in C++: __Z7exampleic

Update: As GManNickG notes in the comments, the pattern of name mangling is compiler dependent.

Harvey
  • 5,703
  • 1
  • 32
  • 41
2

extern "C", is a keyword to declare a function with C bindings, because C compiler and C++ compiler will translate source into different form in object file:

For example, a code snippet is as follows:

int _cdecl func1(void) {return 0}
int _stdcall func2(int) {return 0}
int _fastcall func3(void) {return 1}

32-bit C compilers will translate the code in the form as follows:

_func1
_func2@4
@func3@4

in the cdecl, func1 will translate as '_name'

in the stdcall, func2 will translate as '_name@X'

in the fastcall, func2 will translate as '@name@X'

'X' means the how many bytes of the parameters in parameter list.

64-bit convention on Windows has no leading underscore

In C++, classes, templates, namespaces and operator overloading are introduced, since it is not allowed two functions with the same name, C++ compiler provide the type information in the symbol name,

for example, a code snippet is as follows:

int func(void) {return 1;}
int func(int) {return 0;}
int func_call(void) {int m=func(), n=func(0);}

C++ compiler will translate the code as follows:

int func_v(void) {return 1;}
int func_i(int) {return 0;}
int func_call(void) {int m=_func_v(), n=_func_i(0);}

'_v' and '_i' are type information of 'void' and 'int'

Dongwei Wang
  • 475
  • 5
  • 14
-2

Here is a quote from msdn

"The extern keyword declares a variable or function and specifies that it has external linkage (its name is visible from files other than the one in which it's defined). When modifying a variable, extern specifies that the variable has static duration (it is allocated when the program begins and deallocated when the program ends). The variable or function may be defined in another source file, or later in the same file. Declarations of variables and functions at file scope are external by default."

http://msdn.microsoft.com/en-us/library/0603949d%28VS.80%29.aspx

Joe Pitz
  • 2,434
  • 3
  • 25
  • 30
  • It is a quote from Microsoft, And the way it has been used for years, You are going to ding me with a quote from Microsoft, I suggest you go take a c class – Joe Pitz Mar 08 '10 at 17:59
  • Right, Microsoft, those world-famous pioneers of easily-understandable documentation. That quote is technically correct, but useless to a beginner. – Samir Talwar Mar 08 '10 at 18:02
  • 3
    Being a "quote from Microsoft" doesn't make it relevant to the question at hand. It's talking about extern in other contexts. – Steve Fallows Mar 08 '10 at 18:04
  • It is much clearer than the above definitions for a beginner than introducing mangling to a beginner. If it is technical correct then why the ding??? – Joe Pitz Mar 08 '10 at 18:06
  • 6
    @Joe, because it's not an answer to the question. `extern` by itself and `extern "C"` do *different* things. – Carl Norum Mar 08 '10 at 18:08
  • 2
    It says nothing about the "C" part. You can't explain extern "c" without mentioning mangling. – Steve Fallows Mar 08 '10 at 18:09
  • Actually I meant to ask for this. I misread the question of "extern in C" to be "extern C". – samoz Mar 08 '10 at 18:18