Is Extern "C" Only Required on the Function Declaration

Is extern C only required on the function declaration?

The 'extern "C"' should not be required on the function defintion as long as the declaration has it and is already seen in the compilation of the definition. The standard specifically states (7.5/5 Linkage specifications):

A function can be declared without a linkage specification after an explicit linkage specification has been seen; the linkage explicitly specified in the earlier declaration is not affected by such a function declaration.

However, I generally do put the 'extern "C"' on the definition as well, because it is in fact a function with extern "C" linkage. A lot of people hate when unnecessary, redundant stuff is on declarations (like putting virtual on method overrides), but I'm not one of them.

Is it required to add 'extern C' in source file also?

Since you mean

extern "C" { ... }

style guards, these declare some functions to be of "C" linkage, rather than "C++" linkage (which typically has a bunch of extra name decoration to support things like overloaded functions).

The purpose, of course, is to allow C++ code to interface with C code, which is usually in a library. If the library's headers weren't written with C++ in mind, then they won't include the extern "C" guards for C++.

A C header written with C++ in mind will include something along the lines of

#ifdef __cplusplus
extern "C" {
#endif

...

#ifdef __cplusplus
}
#endif

to make sure C++ programs see the correct linkage. However, not all libraries were written with C++ in mind, so sometimes you have to do

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

to get the linkage correct. If the header file is provided by someone else then it's not good practice to change it (because then you can't update it easily), so it's better to wrap the header file with your own guard (possibly in your own header file).

extern "C" isn't (AFAIK) ANSI C, so can't be included in normal C code without the preprocessor guards.

In response to your edit:

If you are using a C++ compiler, and you declare a function as extern "C" in the header file, you do not need to also declare that function as extern "C" in the implementation file. From section 7.5 of the C++ standard (emphasis mine):

If two declarations of the same
function or object specify different
linkage-specifications (that is, the
linkage-specifications of these
declarations specify different
string-literals), the program is
ill-formed if the declarations appear
in the same translation unit, and the
one definition rule
applies if the declarations appear in
different translation units. Except
for functions with C++ linkage, a
function declaration without a linkage
specification shall not precede the
first linkage specification for that
function. A function can be declared
without a linkage specification after
an explicit linkage specification has
been seen; the linkage explicitly
specified in the earlier declaration
is not affected by such a function
declaration.

I'm not convinced it's good practice though, since there's the potential for the linkage specifications to diverge by accident (if, for example, the header file containing the linkage specification isn't included in the implementing file). I think it's better to be explicit in the implementation file.

Extern functions in C vs C++

There's [almost] never any need to use the keyword extern when declaring a function, either in C or in C++. In C and in C++ all functions have external linkage by default. The strange habit of declaring functions in header files with extern probably has some historical roots, but it has been completely irrelevant for decades already.

There's one [obscure?] exception from the above in C, which is probably not directly related to what you are asking about: in C language (C99) if in some translation unit a function is defined as inline and also declared as extern (an explicit extern is used) then the inline definition of that function also serves as an external definition. If no declarations with explicit extern are present in the translation unit, then the inline definition is used as "internal" definition only.

P.S. There's such thing as extern "C" in C++, but that is a completely different matter.

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 linkage See 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)
  • extern "C" forces a function to have external linkage (cannot make it static) See Richard's comment: static inside extern "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

How to declare an extern C function inside a function in C++?

From the C++11 standard (in [dcl.link], emphasis mine):

4 Linkage specifications nest. When linkage specifications nest, the innermost one determines the language linkage. A linkage specification does not establish a scope. A linkage-specification shall occur only in namespace scope.

(linkage-specification refers to extern string-literal ..., i.e. extern "C" in your case.)

This means you can't have extern "C" inside of a class or function.

What's the point of declaring SomeOtherFunction inside of SomeFunction? It still has to be a global symbol and visible to the linker.

So why not do this?

#ifdef __cplusplus
extern "C"
#endif
void SomeOtherFunction();

inline void SomeFunction() {
SomeOtherFunction();
}

The following also seems to work:

extern "C" {
inline void SomeFunction() {
extern void SomeOtherFunction();
SomeOtherFunction();
}
}

But it would have the side effect of making SomeFunction also use C linkage (which is hopefully OK as (per your requirements) it needs to be usable from C, too).

Effects of the extern keyword on C functions

We have two files, foo.c and bar.c.

Here is foo.c

#include <stdio.h>

volatile unsigned int stop_now = 0;
extern void bar_function(void);

int main(void)
{
while (1) {
bar_function();
stop_now = 1;
}
return 0;
}

Now, here is bar.c

#include <stdio.h>

extern volatile unsigned int stop_now;

void bar_function(void)
{
if (! stop_now) {
printf("Hello, world!\n");
sleep(30);
}
}

As you can see, we have no shared header between foo.c and bar.c , however bar.c needs something declared in foo.c when it's linked, and foo.c needs a function from bar.c when it's linked.

By using 'extern', you are telling the compiler that whatever follows it will be found (non-static) at link time; don't reserve anything for it in the current pass since it will be encountered later. Functions and variables are treated equally in this regard.

It's very useful if you need to share some global between modules and don't want to put / initialize it in a header.

Technically, every function in a library public header is 'extern', however labeling them as such has very little to no benefit, depending on the compiler. Most compilers can figure that out on their own. As you see, those functions are actually defined somewhere else.

In the above example, main() would print hello world only once, but continue to enter bar_function(). Also note, bar_function() is not going to return in this example (since it's just a simple example). Just imagine stop_now being modified when a signal is serviced (hence, volatile) if this doesn't seem practical enough.

Externs are very useful for things like signal handlers, a mutex that you don't want to put in a header or structure, etc. Most compilers will optimize to ensure that they don't reserve any memory for external objects, since they know they'll be reserving it in the module where the object is defined. However, again, there's little point in specifying it with modern compilers when prototyping public functions.

Should functions be made extern in header files?

From The C Book:

If a declaration contains the extern
storage class specifier, or is the
declaration of a function with no
storage class specifier (or both),
then:

  • If there is already a visible declaration of that identifier with
    file scope, the resulting linkage is
    the same as that of the visible
    declaration;
  • otherwise the result is external linkage.

So if this is the only time it's declared in the translation unit, it will have external linkage.



Related Topics



Leave a reply



Submit