Tentative definition is allowed in C but not in C++.
A tentative definition is any external data declaration that has no storage class specifier and no initializer.
C99 6.9.2/2
A declaration of an identifier for an object that has file scope without an initializer, and
without a storage-class specifier or with the storage-class specifier static, constitutes a
tentative definition. If a translation unit contains one or more tentative definitions for an
identifier, and the translation unit contains no external definition for that identifier, then
the behavior is exactly as if the translation unit contains a file scope declaration of that
identifier, with the composite type as of the end of the translation unit, with an initializer
equal to 0.
So int i
is a tentative definition. The C compiler will combine all of the tentative definitions into a single definition of i
.
In C++ your code is ill-formed due to the One Definition Rule (Section 3.2/1 ISO C++)
No translation unit shall contain more than one definition of any variable, function, class type, enumeration type or template.
// but if I write
int i = 5;
again I get error in C also
Because in that case it no longer remains a tentative definition because of the initializer (5).
Just for the sake of information
J.5.11 Multiple external definitions
There may be more than one external definition for the identifier of an object, with or without the explicit use of the keyword extern; if the definitions disagree, or more than one is initialized, the behavior is undefined (6.9.2).
Also check out this excellent post on external variables.