Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

forward declaration using extern (in context of C/C++)

I was confused whether to use extern for forward declarations of functions in C. The scenario is each function is in separate .c/.cpp file. I understood from going through this question - External linkage of const in C , that if all are .c files I should not use extern for forward declaration irrespective of whether the function is defined in same file or not.

But I would like to know more about this when to explicitly use extern for forward declarations (I think when the function being forward declared is defined in a different language than calling one, extern would be required), and any caveats to be aware of.

like image 463
DevBee Avatar asked Nov 25 '25 12:11

DevBee


1 Answers

I think when the function being forward declared is defined in a different language than calling one, extern would be required.

I should warn you that your question is poorly phrased. I'm pretty sure you're interested in when to use

extern "C" int foo(int);

in C++, but I'm not sure, and I have to hope I'm not wasting my time.

Let's distinguish between compiler and linker. I'm leaving out some details, but nothing that affects the answer to your question.

A forward declaration is used by the compiler. In declaring the function, you give the compiler information about how it is used. You declare function F, and when the compiler runs across F being used, it knows what to do. (In the K&R days, in the absence of a declaration the compiler used defaults, sometimes leading to hilarious results. So now they're mandatory in both C and C++.)

Usually a forward declaration of a function is a functional prototype: it provides the parameter types. In C, that's not strictly necessary. You may write

int foo();

which tells the compiler foo is a function returning int, but not what parameters it takes. It then becomes your responsibility to get those right, because the compiler cannot check.

An extern declaration -- whether of a function or a variable -- notifies the compiler of a symbol and its type, and says the definition will be provided by another module. The compiler leaves a placeholder for the linker to fill later.

If you look at the getopt(3) man page, for example, you'll see optarg is declared extern; it's defined in the C runtime library, but you can use it because it's been declared.

Now we come to the linker, and the extern "C" of C++.

To the linker, a module exposes symbols. Global variables and functions not declared static have external linkage, meaning they can be used by other modules.

In C, there's a 1:1 correspondence between function names and external symbols. The name is the symbol. For example, getopt(3) has a symbol of the same name in the C standard library, libc:

$ nm -g $(find /usr/lib/ -name libc.a) 2>/dev/null | grep 'T getopt' 
0000000000001620 T getopt
0000000000000000 T getopt_long
0000000000000040 T getopt_long_only

In C++, the name is not the symbol. A C++ function can be overloaded; the same name can represent different functions taking different parameters. The compiler constructs a symbol that encodes the parameter types. Compare:

$ echo 'int foo(int foo) { return foo * foo; }' > a.c && cc  -c a.c && nm a.o
0000000000000000 T foo
$ echo 'int foo(int foo) { return foo * foo; }' > a.C && c++ -c a.C && nm a.o
0000000000000000 T _Z3fooi

The encoding of the symbol name is often called name mangling. nm(1) has a demangling feature:

$ echo 'int foo(int foo) { return foo * foo; }' > a.C && c++ -c a.C && nm -C a.o
0000000000000000 T foo(int)

Note that the parameter type appears next to the name.

In C++, extern "C" declares or defines the function as a C function. Here's a definition:

$ echo 'extern "C" int foo(int foo) { return foo * foo; }' > a.C && c++ -c a.C && nm a.o
0000000000000000 T foo
  • In a declaration, it tells the compiler that the function is defined elsewhere, and to use a C symbol.

  • In a definition, it tells the compiler to emit a C symbol, i.e. not mangle the name, so that the function can be used by other C modules.

I hope that answers your question.

like image 147
James K. Lowden Avatar answered Nov 28 '25 02:11

James K. Lowden



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!