Static and extern keywords in C

What does the C standard actually say about these?
2011-09-01
~
6 min read

These keywords used to literally haunt my dreams back in the day, when I was a freshman at BUT. I was just getting grips with C at that time and whenever I tried to use them, I got it all wrong. I’m talking about the magic keywords - static and extern . Both of them have multiple uses in C code and slightly different behavior in each case. For a beginner it might seem like a total anarchy, but it will start to make sense at some point. So, let’s get to the point…

Both of these modifiers have something to do with memory allocation and linking of your code. The C standard[3] refers to them as storage-class specifiers. Using those allows you to specify when to allocate memory for your object and/or how to link it with the rest of the code.  Let’s have look on what exactly is there to specify first.

Linking in C

There are three types of linkage - external, internal and none. Each declared object in your program (i.e. variable or function) has some kind of linkage - usually specified by the circumstances of the declaration. Linkage of an object says how is the object propagated through the whole program. Linkage can be modified by both keywords extern and static .

External Linkage

Objects with external linkage can be seen (and accessed) through the whole program across the modules. Anything you declare at file (or global) scope has external linkage by default. All global variables and all functions have external linkage by default.

Internal Linkage

Variables and functions with internal linkage are accessible only from one compilation unit - the one they were defined in. Objects with internal linkage are private to a single module.

No Linkage

No linkage makes the objects completely private to the scope they were defined in. As the name suggests, no linking is done. This applies to all local variables and function parameters, that are only accessible from within the function body, nowhere else.

Storage duration

Another area affected by these keywords is storage duration, i.e. the lifetime of the object through the program run time. There are two types of storage duration in C - static and automatic.

Objects with static storage duration are initialized on program startup and remain available through the whole runtime. All objects with external and internal linkage have also static storage duration. Automatic storage duration is default for objects with no linkage. These objects are allocated upon entry to the block in which they were defined and removed when the execution of the block is ended. Storage duration can be modified by the keyword static .

Static

There are two different uses of this keyword in the C language. In the first case, static modifies linkage of a variable or function. The ANSI standard states:

If the declaration of an identifier for an object or a function has file scope and contains the storage-class specifier static , the identifier has internal linkage.

This means if you use the static keyword on a file level (i.e. not in a function), it will change the object’s linkage to internal, making it private only for the file or more precisely, compilation unit.

/* This is file scope */

int one; /* External linkage. */
static int two; /* Internal linkage. */

/* External linkage. */
int f_one()
{
    return one;
}

/* Internal linkage. */
static void f_two()
{
    two = 2;
}

int main(void)
{
    int three = 0; /* No linkage. */

    one = 1;
    f_two();

    three = f_one() + two;

    return 0;
}

The variable and function() will have internal linkage and won’t be visible from any other module.

The other use of static keyword in C is to specify storage duration. The keyword can be used to change automatic storage duration to static. A static variable inside a function is allocated only once (at program startup) and therefore it keeps its value between invocations. See the example from Stack Overflow[2].

#include <stdio.h>

void foo()
{
    int a = 10;
    static int sa = 10;

    a += 5;
    sa += 5;

    printf("a = %d, sa = %d\n", a, sa);
}

int main()
{
    int i;

    for (i = 0; i < 10; ++i)
        foo();
}

The output will look like this:

a = 15, sa = 15
a = 15, sa = 20
a = 15, sa = 25
a = 15, sa = 30
a = 15, sa = 35
a = 15, sa = 40
a = 15, sa = 45
a = 15, sa = 50
a = 15, sa = 55
a = 15, sa = 60

Extern

The extern keyword denotes, that “this identifier is declared here, but is defined elsewhere”. In other words, you tell the compiler that some variable  will be available, but its memory is allocated somewhere else. The thing is, where? Let’s have a look at the difference between declaration and definition of some object first. By declaring a variable, you say what type the variable is and what name it goes by later in your program. For instance you can do the following:

extern int i; /* Declaration. */
extern int i; /* Another declaration. */

The variable virtually doesn’t exist until you define it (i.e. allocate memory for it). The definition of a variable looks like this:

int i = 0; /* Definition. */

You can put as many declaration as you want into your program, but only one definition within one scope. Here is an example that comes from the C standard:

/*  definition, external linkage */
int i1 = 1;
/*  definition, internal linkage */
static int i2 = 2;
/*  tentative definition, external linkage */
int i3;

/*  valid tentative definition, refers to previous */
int i1;
/*  valid tenative definition, refers to previous */
static int i2;
/*  valid tentative definition, refers to previous */
int i3 = 3;

/* refers to previous, whose linkage is external */
extern int i1;
/* refers to previous, whose linkage is internal */
extern int i2;
/* refers to previous, whose linkage is external */
extern int i4;

int main(void) { return 0; }

This will compile without errors.

Summary

Remember that static - the storage-class specifier and static storage duration are two different things. Storage duration is a attribute of objects that in some cases can be modified by static , but the keyword has multiple uses.

Also the extern keyword and external linkage represent two different areas of interest. External linkage is an object attribute saying that it can be accessed from anywhere in the program. The keyword on the other hand denotes, that the object declared is not defined here, but someplace else.

Sources