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 partiallystatic
and partiallyextern
?
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 invoid 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
How to Combine Std::Bind(), Variadic Templates, and Perfect Forwarding
Is It Illegal to Invoke a Std::Function<Void(Args...)> Under the Standard
Why C++ Doesn't Support Named Parameter
Sse2 Intrinsics - Comparing Unsigned Integers
How to Call the Class's Destructor
Wrap Overloaded Function via Std::Function
Potential Problem in "Swapping Values of Two Variables Without Using a Third Variable"
How Concatenate a String and a Const Char
Does Calling a Destructor Explicitly Destroy an Object Completely
How to Know Underlying Type of Class Enum
Assert That Code Does Not Compile
Convert Std::String to Qstring
Stl Ordering - Strict Weak Ordering
Direct C Function Call Using Gcc's Inline Assembly
How to Get Process Handle from Process Id
Forward Declaration & Circular Dependency
Why Does My Stl Code Run So Slowly When I Have the Debugger/Ide Attached