Qualifiers: Extern, Static and Const in C Language
[Prepared By: Akash Musale, Roll No: 101]
1. Extern:
a. Significance: At compile time
b. Syntax:
i. extern DataType VarName;
ii. extern ReturnType FunctionName(DataType argv1, DataType argv2, …);
c. Can be applied to:
i. Global Variables
ii. Functions (All functions in C are always global except in static scenario, covered later)
iii. Local Variables
d. Description:
Extern keyword is used to help compiler understand the type definition of a variable which is not defined using a data
definition statement in current C source file. Adding an extern qualifier to any data definition statement, makes it a type
declaration statement and the variable is no more allocated any memory in any static sections of the current file.
That is, when the current C source file is converted to its respective assembly and object file, the static sections DO NOT
have any memory allocated to extern variable.
The extern keyword is only looked up until compile time and discarded by compiler once all type references are resolved,
just like any other type declaration statement is discarded by compiler.
The idea behind the extern keyword is to use a variable in current C file for which the space has been allocated in static
sections of another C source file in the same project.
e. Various Cases:
i. Applying extern keyword to global variables:
1. No memory space will be allocated in static section for a global variable with extern qualifier.
2. Compiler will allow reference to such variable in the current file as long as the type information is valid
3. Compiler when converts C file to assembly file, will allocate no space to this variable in static sections,
although you can see the use/references of the variable in data manipulation statements.
4. If the variable is later not found in any other files, an error will be thrown at linking stage by linker
‘Undefined reference to variable’.
ii. Applying extern keyword to functions:
1. No label/code will be generated in respective text section of assembly file for the function.
2. Compiler will allow call to the function as long as type information is valid/matching.
3. Compiler when converts C file to assembly file, will only convert statements calling/referencing the function.
4. If the definition of function is later not found in any other files, an error will be thrown at linking stage by
linker ‘Undefined reference to function’.
iii. Applying extern keyword to local variables:
1. Memory allocation in auto storage location instruction will be generated (Doubtful, but seen on GNU GCC)
2. The reference/use of variable will be done using variable name (as if it is a global variable) instead of offset
from esp register.
3. If the definition of variable is not found later in other files static section, an error will be thrown at linking
stage, ‘undefined reference to variable’
2. Static:
a. Significance: At compile time and linking time
b. Syntax:
i. static DataType VarName;
ii. static ReturnType FunctionName(DataType argv1, DataType argv2, …);
c. Can be applied to:
i. Global Variables
ii. Functions
iii. Local Variables
d. Description:
Static keyword is used to restrict the visibility of a global variable / function from project wide visibility to file wide visibility.
Static keyword is used to change the lifetime of a local variable from “lifetime same as function’s lifetime” to “lifetime
same as entire projects lifetime”.
e. Various Cases:
i. Static global variables:
1. When a global variable is applied static qualifier, the variable’s visibility will be restricted to file wide.
Qualifiers: Extern, Static and Const in C Language
[Prepared By: Akash Musale, Roll No: 101]
2. Making a global variable static removes the “.globl” directive for the variable in assembly file and hence its
entry in the symbol table is marked with ‘l’ (for local, file wide visibility) instead of ‘g’ (for global, project
wide visibility)
3. The section of a global static variable will be either “.data” or “.bss” depending upon whether it is initialized
or uninitialized. (i.e., there is no change in the section for a global static variable)
ii. Static functions:
1. When a function is applied static qualifier, the functions visibility will be restricted to file wide discarding its
TRULY GLOBAL property.
2. Making a function static removes the “.globl” directive for the function in assembly file and hence its entry
in the symbol table is marked with ‘l’ (for local, file wide visibility) instead of ‘g’ (for global, project wide
visibility)
3. The section remains same - “.text”
iii. Static local variables:
1. When a local variable is applied static qualifier, the variable’s lifetime changes from “same as function’s
lifetime” to “same as project’s lifetime”.
2. Making a local variable static change its section from ‘Auto Storage’ section to one of the static sections
depending upon whether the local variable is initialized or uninitialized. (Either .bss, .data, .rodata (In case
of const static) or in .lcomm (local common memory area) section in case of gcc compiler)
3. Note : In case of gcc where local static variables are store in .lcomm section, name mangling is used for
naming the variables in assembly as there are chances of same name static variables in two different
functions.
3. Const:
a. Significance : At compile time
b. Syntax :
i. const DataType VarName;
c. Can be applied to:
i. Global Variables
ii. Local Variables
iii. Note : Functions are by default read-only / const
d. Description:
Const qualifier to a global variable makes it a read-only variable. Using the variable as a l-value is restricted by compiler and
if compiler finds a value being written to a const global variable it throws as error and stops the compilation process.
Similarly, a local const variable is also made read-only and using the const variable as l-value throws as error at compile
time itself.
When a global variable is made const, its storage section changes from .bss or .data to .rodata.
Contrary, the storage section of local const variable remains same i.e., ‘Auto Storage’ section
e. Various cases:
i. Global const variable
1. Storage section changes to .rodata
2. Cannot be used as a l-value, checked while compiling the source file
3. Is made read only.
ii. Local const variable
1. Storage section remains same ‘Auto Storage’
2. Cannot be used as a l-value, checked while compiling the source file
3. Is made read only
f. CONST POINTER AND POINTEE SCENARIOS:
i. Pointer to const data : const int *p;
1. Storing address of a variable(inherently may or may not be a const variable) makes the pointee (the variable
at which pointer is pointing) to be treated like a const variable when used w.r.t pointer.
2. So, one cannot use *p to change the value of pointee.
ii. Const pointer data : int *const p;
1. Similar to any const variable where one cannot change the value of const variable and the value can be set
only on initialization.
2. In this case, the pointer is const, so on initialization itself an address must be stored in the pointer and later
the address in pointer cannot be changed to make it to point to another pointee.
iii. Const pointer to const data : const int *const p;
1. Combination of 1st and 2nd point.
Qualifiers: Extern, Static and Const in C Language
[Prepared By: Akash Musale, Roll No: 101]
2. Both the pointer and pointee are treated as const.
3. Since pointer is const we will need to initialize the pointer with address of some variable and later in the
program value of the pointee cannot be updated as it is also const in this case.
iv. Non const pointer to const data: int *p = &const_variable;
1. There are two sub scenarios for this case:
a. When the const pointee is global variable
i. When we store the address of a global const variable in non-const pointer and we try to
update the value of variable using pointer(*p = 10), a segmentation fault will occur as
the global const variables are stored in .rodata section.
ii. When an application tried to update the value of a data from .rodata section, OS
terminates the application immediately.
b. When the const pointee is local variable
i. Unlike global variable, when we store the address of a local const variable in non-const
pointer and we try to change the value of pointee, the same is allowed.
ii. This is because the local const variable is stored in ‘Auto Storage’ section which is a
read/write section.
iii. In both cases, however, the compiler warns the developer that storing address of a const
variable inside a non-const pointer is forcing it to discard the const property of the const
variable which is not a good practice.
4. Possible combinations of various qualifiers:
a. Extern
i. Static – Make no sense, as both the qualifiers contradict each other
ii. Const – Valid
b. Static
i. Const – Valid
5. Extern with const:
a. All the properties of extern and const are retained together.
b. Extern makes sure that no memory is assigned to global variables in any static sections and const makes sure that with const
property one cannot write to the global variable.
c. In case of local variable, const property makes sure that variable is not written to in the current function.
6. Static with const:
a. All the properties of static and const are retained together.
b. Static makes sure that the visibility of global variable is restricted to file wide instead of project wide and const makes sure that
the variable is not written to anywhere in the program.
c. For local static const variables, the storage section of the variable changes from “Auto Storage” section to .rodata section. Since
it is in .rodata section the const property is maintained and it being a static section the static property of local variable is also
maintained.