tags:

views:

203

answers:

4

AFAIK, extern keyword should be used for declaration and no value can be associated with the variable being declared with extern keyword. But supposing I write a statement like

extern int i = 10;

Should the compiler flag an error for the same? I have seen some compilers being tolerant and ignoring this? Why is this so? What does the 'C' standard says about this?

EDIT: @All, Thanks for the answers. I have a doubt still though. Suppose I have the definition for this variable without the extern linkage in another file say a.c and I add this statement in b.c. Still is it Ok for the compiler not to flag an error? Does it come under redefintion?

+2  A: 

That's valid syntax, there is even an essentially identical example in the C99 standard. (See §6.9.2-4.)

It's true that the examples are not normative but I believe it was intended to be legal syntax. The compiler will often output a warning, because it doesn't really accomplish anything.

4 EXAMPLE 1

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
DigitalRoss
If it really doesn't accomplish anything why is it allowed?
Jay
Lots of keywords and syntax happen to be the default interpretation in any given place. For example, inside a function `int i;` and `auto int i;` are the same definition. While adding `auto` doesn't accomplish anything specific, allowing it provides a consistent use of the storage class specifier.
DigitalRoss
A: 

The extern keyword indicates that the given variable is allocated in a different module. It has nothing to do with access to that variable. It's perfectly legal to assign to assign to an extern variable.

JSBangs
Firstly, the variable in the OP is allocated in *this* module, since the declaration in the OP is actually a *definition*. `extern` doesn't say that something is "in a different module". It just gives something external linkage. Secondly, there's no assignment in the OP. It is an initialization, not assignment.
AndreyT
Note that this is and example initialisation not assignment.
Clifford
A: 

The purpose of extern keyword is to give the entity external linkage. Whether it is used in a declaration in a or definition makes no difference. There's absolutely no error in the code you posted.

If you prefer to think about it in terms of "export vs. import", then extern keyword applied to a non-defining declaration means that we are importing an entity defined in some other translation unit. When extern keyword applied to a definition, it means that we are exporting this entity to be used by other translation units. (Although it is worth noting that "export vs. import" is not exactly a standard way of thinking about the concept of C linkage.)

The reason you won't see the keyword used in definitions very often is because in C file-scope definitions have external linkage by default. So writing

extern int i = 10;

is valid, but redundant, since it is equivalent to plain

int i = 10;

Yet, from time to time in the actual code you might see people using this keyword with function declarations and definitions, even though it is superfluous there as well

extern void foo(int i); /* `extern` is superfluous */
...
extern void foo(int i) /* `extern` is superfluous */
{
  /* whatever */
}
AndreyT
I down-voted this in error, and was too late to correct it. To redress the balance I found another answer you gave I liked and upped it. Not that it looks like you need it ;) Apologies.
Clifford
+2  A: 

The following code ;

extern int i ;

declares a variable i, but does not instantiate it. If it is not also defined in the same compilation unit, the linker will attempt to resolve it from the object files and libraries that comprise the final executable.

However your example:

extern int i = 10 ;

initialises the object, and therefore must also instantiate it. In this case the extern keyword is redundant because the object is initialised in the same compilation unit (in fact the same statment). It is equivalent to:

extern int i ;  // redundant
int i = 10 ;

Although in this last example the extern keyword is redundant, it is exactly equivalent to what you have when a global variable is declared in a header file, and instantiated in a source file that also includes that header (as it should, to allow the compiler to perform type checking).

You can test this as follows:

extern int i ;
int main()
{
    i = 10 ;
}

The above will cause a linker error for unresolved variable i. Whereas:

extern int i = 10 ;
int main()
{
    i = 10 ;
}

will link without problem.

Clifford