Recent from talks
Nothing was collected or created yet.
External variable
View on WikipediaThis article needs additional citations for verification. (January 2017) |
In the C programming language, and its predecessor B, an external variable is a variable defined outside any function block. On the other hand, a local (automatic) variable is a variable defined inside a function block.
As an alternative to automatic variables, it is possible to define variables that are external to all functions, that is, variables that can be accessed by name by any function. (This mechanism is rather like Fortran COMMON or Pascal variables declared in the outermost block.) Because external variables are globally accessible, they can be used instead of argument lists to communicate data between functions. Furthermore, because external variables remain in existence permanently, rather than appearing and disappearing as functions are called and exited, they retain their values even after the functions that set them have returned.
Definition, declaration and the extern keyword
[edit]extrn
[edit]In B, all variables must be declared, as one of auto, extrn, or implicitly as function arguments.[1] An external variable is defined outside functions, has a lifetime of the whole program execution, and introduced to function by the mean of extrn declaration.
Using the following code in the tutorial as an example: [1]
main( ) {
extrn a, b, c;
putchar(a); putchar(b); putchar(c); putchar('!*n');
}
a 'hell';
b 'o, w';
c 'orld';
a, b, c are all external variables of the program defined outside functions, and introduced to the main function by extrn declarations.
extern
[edit]To understand how external variables relate to the extern keyword, it is necessary to know the difference between defining and declaring a variable. When a variable is defined, the compiler allocates memory for that variable and possibly also initializes its contents to some value. When a variable is declared, the compiler requires that the variable be defined elsewhere. The declaration informs the compiler that a variable by that name and type exists, but the compiler does not need to allocate memory for it since it is allocated elsewhere.
The extern keyword means "declare without defining". In other words, it is a way to explicitly declare a variable, or to force a declaration without a definition. It is also possible to explicitly define a variable, i.e. to force a definition. It is done by assigning an initialization value to a variable. If neither the extern keyword nor an initialization value are present, the statement can be either a declaration or a definition. It is up to the compiler to analyse the modules of the program and decide.
A variable must be defined exactly once in one of the modules of the program. If there is no definition or more than one, an error is produced, possibly in the linking stage. A variable may be declared many times, as long as the declarations are consistent with each other and with the definition (something which header files facilitate greatly). It may be declared in many modules, including the module where it was defined, and even many times in the same module. But it is usually pointless to declare it more than once in a module.
An external variable may also be declared inside a function. In this case the extern keyword must be used, otherwise the compiler will consider it a definition of a local (automatic) variable, which has a different scope, lifetime and initial value. This declaration will only be visible inside the function instead of throughout the function's module.
The extern keyword applied to a function prototype does absolutely nothing (the extern keyword applied to a function definition is, of course, non-sensical). A function prototype is always a declaration and never a definition. Also, in standard C, a function is always external, but some compiler extensions allow a function to be defined inside a function.
An external variable must be defined, exactly once, outside of any function; this sets aside storage for it. The variable must also be declared in each function that wants to access it; this states the type of the variable. The declaration may be an explicit
externstatement or may be implicit from context. ... You should note that we are using the words definition and declaration carefully when we refer to external variables in this section. Definition refers to the place where the variable is created or assigned storage; declaration refers to places where the nature of the variable is stated but no storage is allocated.
Scope, lifetime and the static keyword
[edit]An external variable can be accessed by all the functions in all the modules of a program. It is a global variable. For a function to be able to use the variable, a declaration or the definition of the external variable must lie before the function definition in the source code. Or there must be a declaration of the variable, with the keyword extern, inside the function.
The static keyword (static and extern are mutually exclusive), applied to the definition of an external variable, changes this a bit: the variable can only be accessed by the functions in the same module where it was defined. But it is possible for a function in the same module to pass a reference (pointer) of the variable to another function in another module. In this case, even though the function is in another module, it can read and modify the contents of the variable—it just cannot refer to it by name.
It is also possible to use the static keyword on the definition of a local variable. Without the static keyword, the variable is automatically allocated when the function is called and released when the function exits (thus the name "automatic variable"). Its value is not retained between function calls. With the static keyword, the variable is allocated when the program starts and released when the program ends. Its value is not lost between function calls. The variable is still local, since it can only be accessed by name inside the function that defined it. But a reference (pointer) to it can be passed to another function, allowing it to read and modify the contents of the variable (again without referring to it by name).
External variables are allocated and initialized when the program starts, and the memory is only released when the program ends. Their lifetime is the same as the program's.
If the initialization is not done explicitly, external (static or not) and local static variables are initialized to zero. Local automatic variables are uninitialized, i.e. contain "trash" values.
The static keyword applied to a function definition changes the linkage of the function so that it is only visible from the translation unit where its definition is located. This prevents the function from being called by name from outside its module (it remains possible to pass a function pointer out of the module and use that to invoke the function). Declaring a function using the static keyword is also a good way to keep its name short while avoiding name clashes.
Example (C programming language)
[edit]File 1:
// Explicit definition, this actually allocates
// as well as describing
int global_variable;
// Function prototype (declaration), assumes
// defined elsewhere, normally from include file.
void someFunction(void);
int main(void) {
global_variable = 1;
someFunction();
return 0;
}
File 2:
// Implicit declaration, this only describes and
// assumes allocated elsewhere, normally from include
extern int global_variable;
// Function header (definition)
void someFunction(void) {
++global_variable;
}
In this example, the variable Global_Variable is defined in File 1. In order to utilize the same variable in File 2, it must be declared. Regardless of the number of files, a global variable is only defined once; however, it must be declared in any file outside of the one containing the definition.
If the program is in several source files, and a variable is defined in file1 and used in file2 and file3, then extern declarations are needed in file2 and file3 to connect the occurrences of the variable. The usual practice is to collect extern declarations of variables and functions in a separate file, historically called a header, that is included by #include at the front of each source file. The suffix .h is conventional for header names.
The normal methodology is for allocation and actual definitions to go into .c files, but mere declarations and prototypes do not allocate and just describe the types and parameters so that the compiler can work correctly, and that information belongs in a .h header file that others can safely include without any possible conflict.
See also
[edit]- Declaration – Programming language construct specifying an identifier's properties
- Function prototype – Declaration of a function's name and type signature but not body
- Global variable – Computer programming, a variable accessible throughout a computer program
- Linker (computing) – Program that combines intermediate build files into an executable file
- Local variable – Computer programming, a variable only usable in a portion of a program (the scope)
- Scope – Part of a computer program where a given name binding is valid
- Static variable – Programming variable that persists for the lifetime of the program
- The C Programming Language – Book by Brian Kernighan and Dennis Ritchie
References
[edit]External links
[edit]- Microsoft C Language Reference: Storage-Class Specifiers for External-Level Declarations
- "The C Standard (C99 with Technical corrigenda TC1, TC2, and TC3 included)" (PDF). (3.61 MiB). In particular, see sections 6.2.2 (Linkage of identifiers), 6.2.4 (Storage duration of objects), 6.7.1 (Storage-class specifiers) and 6.9 (External definitions).
External variable
View on Grokipediaextern keyword is used in a declaration, specifying the variable's type without allocating storage, thus enabling modular code organization in large programs.[3] Unlike local variables, external variables are initialized to zero if not explicitly set and can lead to issues like namespace pollution if overused, prompting best practices that favor limiting their scope to necessary global state.[4] This mechanism, rooted in C's design for efficient linking, contrasts with internal static variables, which restrict visibility to the defining file despite similar declaration placement.[2]
Definition and Purpose
Core Definition
In programming languages such as C and C++, an external variable refers to an object with external linkage, defined in one translation unit (source file) and accessible in other translation units through compatible declarations, thereby enabling the sharing of data across separately compiled modules without redundant definitions.[5][6] This mechanism ensures that a single instance of the variable exists program-wide, promoting modularity by decoupling the definition from its uses while allowing independent compilation of source files.[5] Key characteristics of external variables include their global accessibility across translation units, initialization at program startup (with zero-initialization if no explicit initializer is provided), and static storage duration, meaning they persist for the entire duration of program execution and retain their values between function calls.[5][6] According to the ISO C standard (e.g., §6.2.2), identifiers with external linkage—typically those declared at file scope without a storage-class specifier—designate the same entity across the program, requiring exactly one external definition if used in an expression.[5] In C++, the concept aligns closely, with external linkage applying to names at namespace scope unless specified otherwise, ensuring visibility outside the defining translation unit (§6.6).[6] The standards also introduce tentative definitions for external variables: a file-scope declaration without an initializer constitutes a tentative definition, which becomes a full definition (implicitly zero-initialized) if no explicit definition appears in the translation unit (§6.9.2).[5] This feature, rooted in C89/C90 and carried forward in subsequent ISO standards, supports flexible declaration practices while enforcing the one-definition rule to prevent multiple instances.[5] The primary purpose of external variables is to facilitate modular programming, where shared state is maintained across components without compromising compilation independence.[6]Historical Context and Terminology
The concept of external variables emerged in the early 1970s during the development of the C programming language by Dennis Ritchie at Bell Labs, as part of efforts to create a systems programming language capable of supporting modular compilation and linking of object files, drawing influences from the typeless B language and low-level assembly practices for the PDP-11 minicomputer. This design choice facilitated the construction of the Unix operating system by allowing variables defined in one source file to be referenced in others, promoting separate compilation without sacrificing efficiency in resource-constrained environments like the PDP-11. Prior to C's standardization, early assemblers such as the PDP-11's MACRO-11 used variants like the .EXTRN directive to declare external symbols for resolution during linking, a mechanism that directly informed C's approach to inter-file references and was occasionally emulated in non-standard C preprocessors for compatibility with assembly code integration. In the initial K&R C specification (1978), global variables at file scope implicitly carried external linkage without requiring an explicit storage class specifier like extern for their declaration, treating uninitialized globals as tentative definitions that could be resolved at link time. The ANSI C standard (X3.159-1989) formalized and refined this by mandating the extern keyword for declarations that do not serve as definitions, ensuring a strict one-definition rule across translation units to prevent multiple allocations and enhance portability, a shift from K&R C's more permissive common model that allowed redundant definitions.[7] This evolution addressed ambiguities in pre-standard C, where the absence of explicit linkage indicators could lead to implementation-defined behaviors during linking.[7] Standards documentation emphasizes the linkage aspect to distinguish external linkage from internal linkage (e.g., via static), aligning with the focus on one-definition semantics.[7]Declaration and Keywords
The extern Keyword
Theextern keyword serves as a storage-class specifier in the C programming language, primarily used to declare identifiers—such as variables and functions—with external linkage, thereby indicating that their actual definition and storage allocation occur elsewhere in the program, often in a different translation unit. This mechanism allows modules to reference shared entities without duplicating their definitions, facilitating modular program design across multiple source files. According to the C99 standard, extern declarations do not allocate storage and are essential for establishing compatibility across declarations.[5]
The syntax for an extern declaration of a variable is extern followed by the type and identifier, such as:
extern int global_counter;
extern int global_counter;
int global_counter = 0;. The GNU C manual emphasizes that extern declarations can omit details like array sizes (e.g., extern int array[];), relying on the definition elsewhere for completeness. In contrast, including an initializer with extern (e.g., extern int x = 5;) transforms it into a definition, allocating storage at file scope.[8]
Regarding placement, extern can appear at file scope (outside any function body), where it contributes to external declarations with file scope visibility, or within a block (inside a function), where it declares the identifier with block scope but external linkage, allowing access to file-scope entities from nested contexts. The C99 standard specifies that extern is optional at file scope for external linkage but required in block scope to override the default internal linkage for local declarations. This flexibility supports its common use in header files for multi-file projects, enabling compilation units to reference variables defined in a single source file without redefinition.[5]
The effects of extern include signaling the compiler to defer resolution of the identifier to the linker, which locates the definition across object files, and explicitly assigning external linkage to prevent the default internal linkage that applies to certain file-scope identifiers without specifiers. This is crucial in large programs, as it ensures symbols are uniquely identifiable program-wide. Common pitfalls arise from misuse: multiple definitions of the same external variable (e.g., without extern in multiple files) lead to undefined behavior, typically resulting in linker errors during the build process. Furthermore, uninitialized extern declarations at file scope do not allocate storage and require a definition elsewhere; their absence leads to linker errors.[5]
Definition vs. Declaration
In the C programming language, a definition of an external variable allocates storage for it and may optionally initialize its value, such as in the declarationint global_var = 10;, and such a definition is permitted only once across the entire program to avoid multiple allocation.[9] In contrast, a declaration of an external variable, typically using the extern keyword like extern int global_var;, merely refers to the variable's existing definition without allocating storage, allowing multiple declarations in different translation units or the same unit as needed for access.[9]
The C standard (ISO/IEC 9899) further distinguishes tentative definitions, which are external declarations without an initializer and lacking a storage-class specifier, such as int x;; if no other definition for the identifier appears in the translation unit, the tentative definition becomes a full definition with implicit zero initialization at the end of the translation unit.[10] An extern declaration does not allocate storage, ensuring it only references a prior definition elsewhere.[9]
Regarding initialization, external variables that are not explicitly initialized in their definition are automatically initialized to zero, as required for objects with static storage duration.[10] In C, const-qualified external variables are zero-initialized if not explicitly initialized in their definition.[5]
Linkage, Scope, and Lifetime
External Linkage
External linkage is a property in programming languages like C and C++ that allows an identifier, such as a variable, to be shared across multiple translation units, enabling the linker to associate all references to that identifier with a single definition.[11] This linkage type makes the name visible to the linker, facilitating resolution during the program's assembly from separate object files.[12] In C and C++, external linkage for variables is achieved by default for declarations at file (or namespace) scope without thestatic storage-class specifier. (Section 6.2.2, ¶4) For instance, a variable declared as int global_var; outside any function has external linkage, allowing it to be accessed from other files via a matching declaration.[11] (Section 3.5/4) Explicitly, the extern keyword can be used in declarations to indicate external linkage, as in extern int global_var;, instructing the compiler to expect a definition elsewhere and defer resolution to the linker. (Section 6.2.2, ¶3) In C++, this applies similarly at namespace scope, though const-qualified variables require extern to gain external linkage.[11] (Section 3.5/3)
The linker plays a crucial role by examining symbols with external linkage from all object files and libraries, resolving references to a unique definition that matches in type and compatibility.[12] If multiple definitions exist, or if a referenced symbol lacks a definition, the linker reports an error, such as an "unresolved external symbol," ensuring one-definition rule compliance. (Section 6.9) This process binds all declarations of the same external identifier across translation units to the same entity, provided their types are compatible.[11] (Section 3.5/5)
The C11 standard (ISO/IEC 9899:2011) formalizes external linkage in Section 6.2.2, stating that an identifier for an object at file scope without a storage-class specifier, or with extern, has external linkage, denoting the same object across the program. (Section 6.2.2, ¶¶2-6) Similarly, the C++11 standard (ISO/IEC 14882:2011) in [basic.link] specifies that namespace-scope variables without internal linkage qualifiers default to external linkage, allowing inter-unit sharing.[11] (Section 3.5/2-4) These rules ensure consistent behavior in multi-file programs.
Scope and Visibility
External variables, when declared outside of any function or block, possess file scope, meaning their visibility begins at the point of declaration and extends to the end of the translation unit (the source file after preprocessing).[13] This scope ensures that the variable is accessible from any point in the file following its declaration, including within nested blocks such as functions or compound statements.[13] Within the same file, external variables are visible and usable in any nested scope after their declaration, allowing functions defined later in the file to reference them directly without additional qualifiers.[13] For access from other files, an explicitextern declaration is required in those translation units, enabling the compiler to recognize the variable's existence and linkage while deferring its definition to the originating file; in C, this process does not involve name mangling, preserving simple symbol names for the linker. However, external variables cannot be accessed or referenced prior to their declaration within the same file, enforcing a strict forward-declaration rule to avoid undefined behavior.[13]
In C++, external variables follow similar file scope rules at namespace scope, but visibility across files is influenced by name mangling, where the compiler encodes additional information (such as type details) into the symbol name to support features like function overloading.[14] This mangling can complicate direct access from other files unless mitigated by the extern "C" linkage specification, which disables mangling and restores C-style visibility for compatibility. Forward references to external variables in C++ also require prior declaration, and unlike functions, variables lack prototypes, so usage must occur after the declaration point in the scope.[15]
Storage Duration and Lifetime
External variables in C possess static storage duration, meaning their lifetime spans the entire execution of the program, from startup to termination.[16] This duration ensures that the memory for such variables is allocated prior to the invocation of themain function and remains available until the program exits normally or abnormally.[16] As a result, external variables maintain their state throughout all program phases, including across multiple function calls and translation units, without being reinitialized unless explicitly specified.[16]
Unlike objects with allocated storage duration—such as those created via malloc or calloc—external variables require no explicit allocation or deallocation by the programmer.[16] Their memory management is handled automatically by the runtime environment at the boundaries of program execution, avoiding the need for calls to functions like free and reducing the risk of memory leaks associated with dynamic allocation.[16] This static nature contrasts sharply with automatic storage duration objects, which are confined to block scopes and destroyed upon scope exit.[16]
In multi-threaded programs, external variables with static storage duration are shared across all threads by default, potentially leading to data races if accessed concurrently without synchronization.[16] However, since C11, the _Thread_local storage-class specifier can be combined with external linkage to grant thread storage duration, creating a separate instance per thread with a lifetime tied to that thread's execution.[16] Accessing a thread-local external variable from another thread results in implementation-defined behavior.[16]
The C standard formalizes this in section 6.7.1, which specifies that objects declared with the extern storage-class specifier or possessing external linkage have static storage duration.[16] This provision, consistent from C99 onward, underscores the design intent for external variables to serve as global, persistent data structures in modular programs.[16]
Storage Classes and Comparisons
External Storage Class
The external storage class specifier, denoted by theextern keyword, indicates that a declared object or function possesses external linkage and static storage duration, but does not allocate storage when used in a declaration. This specifier is essential for declaring entities that are defined elsewhere, enabling their use across multiple translation units without redefining them.[17]
Semantically, the external storage class integrates properties of linkage, scope, and storage duration into the declaration of variables, arrays, or functions. At file scope, external linkage is the implicit default for such declarations unless explicitly overridden, ensuring the entity can be accessed program-wide while maintaining a lifetime that spans the entire execution of the program.[17]
According to the C standard in §6.7.1, extern is one of four storage-class specifiers—alongside auto, register, and static—that classify the storage and accessibility attributes of declared identifiers. This classification underscores its role in distinguishing declarations intended for inter-file sharing from those confined to local or internal use.[18]
The specifier applies analogously to arrays and functions as it does to simple variables. For instance, extern int arr[10]; declares an array of 10 integers with external linkage and static duration, presupposing its definition in another source file, while extern int func(void); declares a function prototype accessible from other translation units.[17]
Comparison with Static Storage
External variables and variables declared with the static storage class specifier both feature static storage duration, ensuring their lifetime extends throughout the entire execution of the program. The key distinction between them centers on linkage. The static specifier, when applied to a file-scope variable, imparts internal linkage, confining the variable's visibility and accessibility to the translation unit (source file) in which it is defined, thereby preventing it from being referenced or linked from other files.[17] In contrast, external variables possess external linkage by default (or explicitly via theextern keyword for declarations), enabling them to be shared and accessed across multiple translation units during linking.[17]
These linkage properties align with distinct use cases in software development. Static variables serve as module-private globals, ideal for maintaining internal state within a single file—such as helper counters or buffers—while promoting encapsulation and reducing the risk of naming conflicts or unauthorized modifications from external modules.[7] External variables, however, are suited for shared global state that must be coordinated across files, like system-wide flags or data structures in larger applications.[17]
Syntactically, this contrast is evident in declarations at file scope: static int counter; creates a variable with internal linkage, invisible to the linker outside its file, whereas int global_var; defaults to external linkage, and extern int shared_var; declares a reference to an externally defined variable, exposing it for inter-file use.[19]
In the evolution of C standards, prior to ANSI C89 (based on K&R C), file-scope variables were external by default without qualifiers, with the static keyword specifically added to enable internal linkage and support encapsulation in multi-file programs.[7]
Language-Specific Implementations
In C
In the C programming language, variables declared at file scope without thestatic specifier possess external linkage by default, enabling them to be accessed from other translation units within the same program.[17] The extern keyword is primarily employed to declare such variables in translation units other than the one containing their definition, or to explicitly affirm external linkage when overriding potential internal linkage from prior declarations.[17] A declaration using extern does not allocate storage, distinguishing it from a definition that initializes or allocates the variable, such as int global_var = 0;.[20]
To facilitate multi-file programs, external variable declarations are commonly placed in header files (.h extensions), which are included via the #include directive to ensure consistent type information across source files.[21] These headers typically incorporate include guards—preprocessor directives like #ifndef, #define, and #endif—to prevent multiple inclusions within a single translation unit, thereby avoiding redeclaration errors while allowing safe reuse across files.[21]
Compilers such as GCC and Clang issue warnings for unused external variables declared in a translation unit, detectable via flags like -Wunused-variable, to highlight potential dead code or incomplete implementations.[22][23] At link time, the GNU linker (ld) resolves references to these external symbols by matching declarations to their definitions across object files, ensuring proper symbol binding before producing the executable.[24]
The C11 standard introduced the _Thread_local storage-class specifier, which can be combined with extern to declare thread-local variables with external linkage, allowing such variables to be referenced across translation units while maintaining distinct instances per thread.[17] This combination overrides the static storage duration implied by extern alone, assigning thread storage duration instead, and requires the specifier on all declarations of the object.[17]
In C++
In C++, the handling of external variables largely inherits the semantics from C, where theextern keyword is used to declare variables and functions with external linkage, allowing them to be accessed across multiple translation units without redefinition.[25] This enables a single definition in one source file to be referenced in others via declarations, preventing multiple definition errors during linking. However, C++ introduces name mangling to support features like function overloading and templates, which encodes names of entities with external linkage—including variables in certain contexts—with additional information about types, scopes, and parameters to ensure uniqueness in the object code. This mangling, part of the default "C++" language linkage, differentiates C++ from C, where no such encoding occurs, potentially requiring extern "C" for interoperability to disable mangling and match C's simpler naming convention.
Namespaces in C++ provide a mechanism to organize external variables, and the extern keyword can be used within a namespace declaration to specify external linkage for a variable in that scope. For example, namespace ns { extern int [var](/page/The_Variable); } declares var as an external variable within the ns namespace, allowing it to be defined elsewhere and accessed qualified as ns::var. This qualified form supports modular code organization while maintaining external visibility, though care must be taken with name lookup rules to avoid ambiguities in multi-file projects.
Introduced in C++17, the inline specifier for variables offers an alternative to traditional extern declarations for constants or other globals intended for inclusion in headers, permitting multiple definitions across translation units without linker errors as long as they are identical. For instance, inline int global = 10; can appear in a header and be included in multiple files, with the compiler selecting one definition and treating others as aliases, which simplifies sharing compile-time constants compared to extern alone. This feature addresses common issues with header-only libraries but applies only to variables with external linkage and requires the definition to be odr-used appropriately.
The rules for external linkage in C++ are formalized in ISO/IEC 14882:2011 (C++11) section 3.5, which defines how names with external linkage are shared across translation units, with subsequent standards building upon this foundation. In C++20, the introduction of modules adds a new layer with module linkage, where non-exported names attached to a module do not have external linkage, potentially affecting how extern variables are declared and imported across module interfaces to prevent unintended global visibility.[26] This evolution enhances encapsulation while preserving the core extern mechanism for traditional multi-file linkage.[27]
Practical Examples
Single-File Example
In a single source file, an external variable is typically defined at file scope—outside of any function—without theextern keyword, which grants it external linkage by default, file scope, and static storage duration. This means the variable is accessible throughout the entire file and retains its value across function calls for the duration of the program, as its lifetime begins before main() and ends after program termination. Unlike local automatic variables, which are reinitialized on each function entry, external variables provide persistent storage without requiring explicit redeclaration within the same file.
Consider the following C example, where counter is defined as an external variable and accessed by multiple functions:
#include <stdio.h>
int counter = 0; // Definition with external linkage, file scope, static duration
void increment_and_print(void) {
counter++;
[printf](/page/Printf)("Counter value: %d\n", counter);
}
int main(void) {
increment_and_print(); // Outputs: Counter value: 1
increment_and_print(); // Outputs: Counter value: 2
return 0;
}
#include <stdio.h>
int counter = 0; // Definition with external linkage, file scope, static duration
void increment_and_print(void) {
counter++;
[printf](/page/Printf)("Counter value: %d\n", counter);
}
int main(void) {
increment_and_print(); // Outputs: Counter value: 1
increment_and_print(); // Outputs: Counter value: 2
return 0;
}
counter is initialized to 0 at program startup and persists across calls to increment_and_print(), demonstrating how its static storage duration ensures the value increments sequentially rather than resetting. This behavior aligns with the C standard's rules for objects with external linkage, where no extern declaration is needed for access within the defining file, as the definition itself serves as the visible declaration.
To compile this single-file program, use a command like gcc example.c -o example, which produces an executable without linking issues, as all symbols are resolved internally. The resulting output confirms the variable's persistence:
Counter value: 1
Counter value: 2
Counter value: 1
Counter value: 2
Multi-File Linkage Example
In multi-file C programs, external variables facilitate data sharing by defining the variable once in one source file and declaring it with theextern keyword in other files, typically through a shared header file to promote modularity.[1][28]
The following example illustrates this with a simple integer variable shared, initialized to 5 in one file and accessed and modified in another.
Create a header file shared.h containing the external declaration:
#ifndef SHARED_H
#define SHARED_H
extern int shared;
#endif
#ifndef SHARED_H
#define SHARED_H
extern int shared;
#endif
file1.c, provide the actual definition, which allocates storage and sets the initial value:
#include "shared.h"
int shared = 5; // Single definition across the program
#include "shared.h"
int shared = 5; // Single definition across the program
file2.c, include the header and use the variable, for example, in a main function:
#include <stdio.h>
#include "shared.h"
int main(void) {
[printf](/page/Printf)("Initial value: %d\n", shared);
shared += 1;
[printf](/page/Printf)("Modified value: %d\n", shared);
[return 0](/page/Return_0);
}
#include <stdio.h>
#include "shared.h"
int main(void) {
[printf](/page/Printf)("Initial value: %d\n", shared);
shared += 1;
[printf](/page/Printf)("Modified value: %d\n", shared);
[return 0](/page/Return_0);
}
extern declaration informs the compiler that the variable exists elsewhere, without allocating new storage.[1][30]
To compile and link the program using GCC, first generate object files from each source file separately:
gcc -c file1.c -o file1.o
gcc -c file2.c -o file2.o
gcc -c file1.c -o file1.o
gcc -c file2.c -o file2.o
gcc file1.o file2.o -o program
gcc file1.o file2.o -o program
file2.o to the definition in file1.o, combining the modules into a single executable.[31][30]
A common error arises from duplicate definitions, such as defining int shared = 5; in both file1.c and file2.c, which violates the one definition rule and triggers a linker error like "multiple definition of 'shared'". This is resolved by retaining the definition in only one file and using extern declarations elsewhere.[28][32]
Another frequent issue is an undefined symbol error during linking if the variable is declared with extern but never defined in any file; this is fixed by adding the definition to exactly one source file.[31]
Executing the program with ./program produces the following output, confirming that the modification in file2.c affects the shared value defined in file1.c:
Initial value: 5
Modified value: 6
Initial value: 5
Modified value: 6
