Reputation: 160
What is the difference when I write:-
#include<stdio.h>
int a=10;
main( )
{
printf ("%d", a);
}
And the other one is:-
#include<stdio.h>
main ( )
{
extern int a=10;
printf ("%d", a);
}
Upvotes: 0
Views: 404
Reputation: 310950
For starters according to the C Standard the function main without parameters shall be declared like
int main( void )
This program
#include<stdio.h>
main ( )
{
extern int a=10;
printf ("%d", a);
}
is incorrect. According to the C Standard (6.7.9 Initialization)
5 If the declaration of an identifier has block scope, and the identifier has external or internal linkage, the declaration shall have no initializer for the identifier.
However if you will remove the initializer as for example
#include<stdio.h>
main ( )
{
extern int a;
printf ("%d", a);
}
nevertheless the program will have undefined behavior. According to the C Standard (6.9 External definitions)
5 An external definition is an external declaration that is also a definition of a function (other than an inline definition) or an object. If an identifier declared with external linkage is used in an expression (other than as part of the operand of a sizeof operator whose result is an integer constant), somewhere in the entire program there shall be exactly one external definition for the identifier; otherwise, there shall be no more than one.
Take into account that in the program above the identifier a
has external linkage (6.2.2 Linkages of identifiers)
4 For an identifier declared with the storage-class specifier extern in a scope in which a prior declaration of that identifier is visible,31) if the prior declaration specifies internal or external linkage, the linkage of the identifier at the later declaration is the same as the linkage specified at the prior declaration. If no prior declaration is visible, or if the prior declaration specifies no linkage, then the identifier has external linkage.
A correct program can look like for example the following way
#include <stdio.h>
int main(void)
{
extern int a;
printf( "a = %d\n", a );
return 0;
}
int a = 10;
Its output is
a = 10
In this program there is external definition of the identifier a
with external linkage
int a = 10;
Upvotes: 4
Reputation: 180181
As others have pointed out, your second example does not compile. But this variation does:
#include <stdio.h>
int a = 10;
int main(void) {
extern int a;
printf ("%d", a);
}
Since I take you to be asking about the effect of the extern
storage-class specifier, let's talk about this version of the code.
By default, block-scoped variable declarations have no linkage and declare objects with automatic storage duration. Such a variable is specific to one execution of the innermost containing block, and it cannot be directly accessed from outside. If we declare a block-scope variable extern
, however, we are declaring that in that scope we are using the identifier of a variable with external linkage. That's probably what you mean by a "global variable".
But a block-scope extern
declaration is not permitted to be a definition of the object it declares. For a variable, that means it must not include an initializer, and that it does not reserve any storage for such an object. It merely declares that you intend to refer to an object defined elsewhere. That's pretty pointless in a single-file example, but it is potentially useful for accessing an external variable provided by a different file, without making it accessible to every function in the current file.
Example:
#include <stdio.h>
int main(void) {
extern int a;
printf("%d\n", a);
return 0;
}
int a = 10;
If these separate source files are compiled and linked together then the resulting program has well-defined behavior: it prints "10" followed by a newline to its standard output.
Upvotes: 3
Reputation: 12817
One difference I can think of is redeclaring variables. When declaring a global a
it's OK to declare inside a function another local a
. The compiler will use the local variable and there will be no compilation errors.
However, using extern int a
and then redeclaring int a
will cause a compilation error.
Upvotes: -1
Reputation: 60058
None of my compilers (tcc, gcc, clang) accepts extern int a = 10;
(with an initializer (=10)) at block scope. It's legal at file scope, as evidenced by an example from the standard:
int i1 = 1; // definition, external linkage
static int i2 = 2; // definition, internal linkage
extern int i3 = 3; // definition, external linkage
int i4; // tentative definition, external linkage
static int i5; // tentative definition, internal linkage
int i1; // valid tentative definition, refers to previous
int i2; // 6.2.2 renders undefined, linkage disagreement
int i3; // valid tentative definition, refers to previous
int i4; // valid tentative definition, refers to previous
int i5; // 6.2.2 renders undefined, linkage disagreement
extern int i1; // refers to previous, whose linkage is external
extern int i2; // refers to previous, whose linkage is internal
extern int i3; // refers to previous, whose linkage is external
extern int i4; // refers to previous, whose linkage is external
extern int i5; // refers to previous, whose linkage is internal
where it is no different from int a = 10;
, but both clang and gcc warn against it.
Usually extern
is used to refer to data objects defined elsewhere (it's optional with functions). Using it with definitions, though legal, is unusal.
Upvotes: 2