tags:

views:

1478

answers:

8

My question is about when a function should be referenced with the extern keyword in c.

I am failing to see when this should be used in practice. As I am writing a program all of the functions that I use are made available through the header files I have included. So why would it be useful to extern to get access to something that was not exposed in the header file?

I could be thinking about how extern works incorrectly, and if so please correct me.

Edit: Should you extern something when it is the default declaration without the keyword in a header file?

A: 

When you have that function defined on a different dll or lib, so that the compiler defers to the linker to find it. Typical case is when you are calling functions from the OS API.

Otávio Décio
A: 

If each file in your program is first compiled to an object file, then the object files are linked together, you need extern. It tells the compiler "This function exists, but the code for it is somewhere else. Don't panic."

Chris Lutz
Um, that's how translation is normally done: source files compile to object files, and are then linked. When would you not need extern in that case? Nor would you use #include to get functions, but rather function prototypes. I don't understand what you're talking about.
David Thornley
I seem to be having this problem lately of misreading things. Sorry about that. When I was new to C, I would #include "file.c" to just include the functions in one file directly into the other file. Then I figured out how to use 'extern'. I thought he was making the same mistake I was.
Chris Lutz
+18  A: 

"extern" changes the linkage. With the keyword, the function / variable is assumed to be available somewhere else and the resolving is defered to the linker.

There's a difference between "extern" on functions and on variables: on 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.

bluebrother
A: 

Functions actually defined in other source files should only be declared in headers. In this case, you should use extern when declaring the prototype in a header.

Most of the time, your functions will be one of the following (more like a best practice):

  • static (normal functions that aren't visible outside that .c file)
  • static inline (inlines from .c or .h files)
  • extern (declaration in headers of the next kind (see below))
  • [no keyword whatsoever] (normal functions meant to be accessed using extern declarations)
Eduard - Gabriel Munteanu
Why would you extern when declaring the prototype if this is the default?
lillq
@Lane: Might be a bit biased, but every sane project I've worked on uses the following convention: in headers, declare prototypes only for external functions (hence extern). In .c files, plain prototypes can be used to obviate the need for specific ordering, but they shouldn't be placed in headers.
Eduard - Gabriel Munteanu
+1  A: 

All declarations of functions and variables in header files should be extern.

Exceptions to this rule are inline functions defined in the header and variables which - although defined in the header - will have to be local to the translation unit (the source file the header gets included into): these should be static.

In source files, extern shouldn't be used for functions and variables defined in the file. Just prefix local definitions with static and do nothing for shared definitions - they'll be external symbols by default.

The only reason to use extern at all in a source file is to declare functions and variables which are defined in other source files and for which no header file is provided.


Declaring function prototypes extern is actually unnecessary. Some people dislike it because it will just waste space and function declarations already have a tendency to overflow line limits. Others like it because this way, functions and variables can be treated the same way.

Christoph
Can you give a reason to why "All declarations of functions and variables in header files should be extern."? It look to me from the other responses that they are extern by default.
lillq
@Lane: `extern` is optional for function declarations, but I like to treat variables and functions the same way - at least that's the most reasonable thing I could come up with, as I don't exactly remember why I started doing this ;)
Christoph
+7  A: 

In C, 'extern' is implied for function prototypes, as a prototype declares a function which is defined somewhere else. In other words, a function prototype has external linkage by default; using 'extern' is fine, but is redundant.

(If static linkage is required, the function must be declared as 'static' both in its prototype and function header, and these should normally both be in the same .c file).

Steve Melnikoff
+4  A: 

It has already been stated that the using keyword is redundant, for functions.

As for variables shared across compilation units, you should declare them in a header file with the extern keyword, then define them in a single source file, without the extern keyword. The single source file should be the one sharing the header file's name, for best practice.

aib
+6  A: 

extern tells the compiler that this data is defined somewhere and will be connected with the linker.

With the help of the responses here and talking to a few friends here is the practical example of a use of extern.

Example 1 - to show a pitfall:

File stdio.h:

int errno;
/* other stuff...*/


myCFlie1.c:
#include <stdio.h>

Code...


myCfile2.c:
#include <stdio.h>

Code...

If myCFile1.o and myCFile2.o are linked, each of the c files have separate copies of errno. This is a problem as errno is suppose to be constant over over all linked files.

Example 2 - The fix.

File stdio.h:

extern int errno;
/* other stuff...*/


File stdio.c

int errno;


myCFlie1.c:
#include <stdio.h>

Code...


myCFile2.c:
#include <stdio.h>

Code...

Now if both myCFile1.o and MyCFile2.o are linked by the linker they will both point to the same errno. Thus, solving the implementation with extern.

lillq
The problem isn't that the myCFile1 and myCFile2 modules have a separate copy of errno, it's that they are both exposing a symbol called "errno". When the linker sees this, it doesn't know which "errno" to pick, so it will bail out with an error message.
cwick