Reputation: 33
test.h
#ifndef TEST_H
#define TEST_H
int i;
int i = 1; // why no redefinition error issued?
#endif /* TEST_H */
test.c
#include "test.h"
int main() {
int x;
int x = i; // obviously, a redefinition
return 0;
}
I am really curious about the behavior of an uninitialized global variable in a header file. As far as I know, both "int i;" and "int i = 1" are effective definitions for i but in practice neither clang nor gcc will issue an error for this case. Can anybody explain the detail?
Upvotes: 1
Views: 289
Reputation: 13220
It is tentative definition as explained here.
At the top level of a translation unit (that is, a source file with all the #includes after the preprocessor), every C program is a sequence of declarations, which declare functions and objects with external linkage. These declarations are known as external declarations because they appear outside of any function.
Tentative definitions
A tentative definition is an external declaration without an initializer, and either without a storage-class specifier or with the specifier static.
A tentative definition is a declaration that may or may not act as a definition. If an actual external definition is found earlier or later in the same translation unit, then the tentative definition just acts as a declaration.
int i1 = 1; // definition, external linkage
int i1; // tentative definition, acts as declaration because i1 is defined
extern int i1; // declaration, refers to the earlier definition
extern int i2 = 3; // definition, external linkage
int i2; // tentative definition, acts as declaration because i2 is defined
extern int i2; // declaration, refers to the external linkage definition
If there are no definitions in the same translation unit, then the tentative definition acts as an actual definition with the initializer = 0
(or, for array types, = {0}
).
int i3; // tentative definition, external linkage
int i3; // tentative definition, external linkage
extern int i3; // declaration, external linkage
// in this translation unit, i3 is defined as if by "int i3 = 0;"
Upvotes: 1