What Is Default Storage Class for Global Variables

What is default storage class for global variables?

The default storage duration is static, but default linkage is external. You're not the only one to find it a bit confusing. The C Book (always a good reference) says:

"You'll probably find the interactions
between these various elements to be
both complex and confusing: that's
because they are!"

The section with that quote, Declarations, Definitions and Accessibility, has a helpful table (8.1). The last row describes the case you're interested in. As it notes, data objects with no storage class specifier have external linkage and static duration.

Global variables in C are static or not?

If you do not specify a storage class (that is, the extern or static keywords), then by default global variables have external linkage. From the C99 standard:

§6.2.2 Linkages of identifiers

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

5) If the declaration of an identifier for a function has no storage-class specifier, its linkage is determined exactly as if it were declared with the storage-class specifier extern. If the declaration of an identifier for an object has file scope and no storage-class specifier, its linkage is external.

So even if you don't specify the extern keyword, globals can still be accessed by other source files (so-called translation units), because they can still have an extern declaration for the same variable. If you use the static keyword to specify internal linkage, then even in the presence of an extern declaration for the same variable name in another source file, it will refer to a different variable.

Whether Global Variables in C, static or extern?

Global Variable in C by default corresponds to static storage class but has external linkage. Does this mean it is partially static and partially extern?

The English word “static” has muddled and multiple meanings in C, and, yes, the default for a variable declared outside a function is to have static storage duration and external linkage.

Because there are multiple concepts here and some mixed use of word meanings, we should clarify some terminology and formatting:

  • Use code style to refer to specific text in source code, such as the keyword static. When speaking of static storage duration or external linkage, “static” and “external” are mere English adjectives and should not be in code style.
  • “Global” means visible throughout an entire program. The C standard does not use this word for this purpose. It uses “external” to refer to things that are outside of (external to) any function. (But it also uses “external” for other purposes.) A global variable could not have internal linkage, because it would not be visible throughout the entire program.
  • A variable consists of an object (memory reserved for representing the value) and an identifier (the name). Storage duration is a property of the object. Linkage is a property of the identifier.

The English word “static” generally means unchanging. The C standard uses this word and the keyword static in multiple ways:

  • Static storage duration means the memory for an object is reserved throughout all of program execution.
  • Using the static keyword in a declaration, other than as below, both gives an object static storage duration and, in a declaration outside a function, gives the identifier internal linkage.
  • Using the static keyword inside subscript markers in a parameter declaration, as in void foo(int a[static 3]), indicates that the parameter points to at least the stated number of elements.
  • Static assertions, using _Static_assert, provide compile-time tests (which can help detect bugs or ensure a program is being compiled with expected settings).

These multiple uses are unfortunate and are due at least partly to the history of how the C language was developed.

Understanding static storage class in C

In the formal C terminology specifiers like extern, static, register etc. are called storage-class specifiers, but the actual object properties these specifiers control are called storage duration and linkage.

In your question you seem to be mixing these two unrelated concepts: storage duration and linkage. It is actually linkage that describes external visibility of the object.

All variables defined in file scope have static storage duration (regardless of whether you used the keyword static in the declaration). This simply means that they live forever, but it does not say anything about their external visibility. Meanwhile, variables defined with keyword static have internal linkage, while variables defined without any keywords or with keyword extern have external linkage.

In your example variable Road has static storage duration and external linkage, which is why you can access it directly from other translation units. Variable Count has static storage duration and internal linkage, which is why you can't access it directly from other translation units.

If you declare a variable without a storage class specifier (like Road in your example), it will be treated as so called tentative definition and finally resolve (in your example) to a variable with static storage duration and external linkage. So, from that point of view it is right to say that the default (implied) storage class specifier for file scope variables is actually extern, not static.

Does every variable have a storage class in C?

The keywords auto, static, extern, register, and _Thread_local are referred to in the standard as storage class specifiers, but "objects" (this is the standardese term for what we usually call "variables") don't have storage classes. Instead they have linkage (external, internal, none) and storage duration (static, automatic, thread). In addition, any declaration of an object may or may not be a definition. The storage class specifiers, together with the scope at which the object is declared, and whether or not it has an initializer (int foo vs int foo = 3), control these properties. It's easiest to show how this works with a table:

sc-specifier scope initialized   linkage    storage duration    is a definition
------------ ----- ----------- ------- ---------------- ---------------
auto file no [constraint violation]
auto file yes [constraint violation]
auto block no none automatic yes
auto block yes none automatic yes

none file no external static yes
none file yes external static yes
none block no none automatic yes
none block yes none automatic yes

static file no internal static yes
static file yes internal static yes
static block no none static yes
static block yes none static yes

extern file no external static no
extern file yes external static yes
extern block no external static no
extern block yes external static yes

The term "storage class specifier" is intentionally different from the terms "storage duration" and "linkage" to remind you that the specifiers don't give you independent control over the storage duration and linkage.

The language doesn't give you independent control over storage duration, linkage, and being a definition because the combinations that are unavailable don't make sense. Automatic storage duration only makes sense for variables declared at block scope, not being a definition only makes sense for variables with external linkage (because only they could be defined in another file), and so on.

I left register and _Thread_local out of the table because they are special. register is just like auto except that it also means you're not allowed to take the address of the object. _Thread_local makes the storage duration of the variable be "thread" and doesn't change the linkage; it can be used by itself or with extern or static, but it's a constraint violation to combine it with "auto". I'm not sure what it does if you use it at block scope by itself.

extern storage class and global variables

an extern variable is a declaration of a variable which is defined in another unit.

You declare it in .h file:

extern int global_var;

and if you want to use it in .c file you define it in the global scope. And you should include the .h file in the source file that uses it.

Global variables are ariables which were declared outside of a block.
They can be accessed everywhere in the program.

Please note that it is very important to know the difference between Declaring a variable and Defining it:

  • Declare a variable - There is something with this name, and it has this type. The compiler can use this variable without the need of all the definition of it.
  • Define a variable - Provide all of the information to create this variable.


Related Topics



Leave a reply



Submit