From the C Standard (6.9.2 External object definitions)
1 If the declaration of an identifier for an object has file scope and
an initializer, the declaration is an external definition for the
identifier.
and
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.
And there is an example in the C Standard
int i1 = 1; // definition, external linkage
//...
int i1; // valid tentative definition, refers to previous
So in your program this one declaration
int a = 3;
is an external definition for the identifier a
and this one
int a;
is a tentative definition that refers to the previous external definition of the identifier.
If to use an initializer in the second declaration then you will get two external definitions for the identifier and the compiler will issue an error because only one external definition can exist.
Take into account that C and C++ differ relative to this context,
From the C++ Standard (C.1.2 Clause 6: basic concepts)
6.1
Change: C++ does not have “tentative definitions” as in C. E.g., at
file scope,
int i;
int i;
is valid in C, invalid in C++.
extern
. – Communismextern
that would mean thatint a; ... int a;
would be equivalent toextern int a; ... extern int a;
, but latter doesn't link. – Alberto