16

Wiki says:

The extern keyword means "declare without defining". In other words, it is a way to explicitly declare a variable, or to force a declaration without a definition. It is also possible to explicitly define a variable, i.e. to force a definition. It is done by assigning an initialization value to a variable.

That means, an extern declaration that initializes the variable serves as a definition for that variable. So,

/* Just for testing purpose only */ 
#include <stdio.h>
extern int y = 0;
int main(){
    printf("%d\n", y);
    return 0;
}

should be valid (compiled in C++11). But when compiled with options -Wall -Wextra -pedantic -std=c99 in GCC 4.7.2, produces a warning:

[Warning] 'y' initialized and declared 'extern' [enabled by default]

which should not. AFAIK,

extern int y = 0;  

is effectively the same as

int i = 0;  

What's going wrong here ?

haccks
  • 104,019
  • 25
  • 176
  • 264
  • 5
    [This](http://stackoverflow.com/questions/4268589/warning-in-extern-declaration) might also help. Not the accepted answer, but the one by [AndreyT](http://stackoverflow.com/users/187690/andreyt). Note the last line of the answer in particular: _Just disable this warning in compiler settings (and, please, write a rude letter about it to GCC team)._ – devnull Jun 26 '14 at 17:36
  • @devnull just write an answer, if you don't want rep then make it community wiki – Shafik Yaghmour Jun 26 '14 at 17:42
  • @ShafikYaghmour You could help by upvoting the correct answer and downvoting the _not-so-correct_ in the linked question. – devnull Jun 26 '14 at 17:43
  • @devnull this does not really look like an exact dup, although they are related. – Shafik Yaghmour Jun 26 '14 at 17:44
  • @ShafikYaghmour I didn't say anything at all about being a dup. The `gcc` bug report was the starting point. The other answer seemed to substantiate it. So anything else would seem redundant. – devnull Jun 26 '14 at 17:48
  • You're supposed to put `exter y` in another file – Ryan Jun 26 '14 at 17:51
  • 1
    That seems like a *this might not be what was intended by the programmer* type of warning (such as warning for `if(i=5) {...}`) rather than anything wrong with the code as per the language. Other than that, it's a valid C code. – P.P Jun 26 '14 at 17:56

2 Answers2

9

This code is perfectly valid.

But any compiler is free to issue additional (informative or not) diagnostics:

(C99, 5.1.1.3p1 fn 8) "Of course, an implementation is free to produce any number of diagnostics as long as a valid program is still correctly translated."

What a compiler cannot do is not emitting a diagnostic when there is a constraint or syntax violation.

EDIT:

As devnull put in the OP question comments, Joseph Myers from gcc team explains in a bug report questioning this diagnostic:

"This is a coding style warning - the code is valid, but extremely unidiomatic for C since "extern" is generally expected to mean that the declaration is not providing a definition of the object."

Community
  • 1
  • 1
ouah
  • 142,963
  • 15
  • 272
  • 331
  • 1
    I think the most relevant part of the GCC bug report is: "This is a coding style warning - the code is valid, but extremely unidiomatic for C since "extern" is generally expected to mean that the declaration is not providing a definition of the object." – Étienne Jun 26 '14 at 18:09
  • 1
    I think it might be worth adding the example (which I quote in my answer) from the C99/C11 standards to the bug report. – Jonathan Leffler Jun 26 '14 at 18:14
  • @ShafikYaghmour added an edit to cover part of the bug report content – ouah Jun 26 '14 at 21:34
  • 1
    @ouah you already had my +1 but I appreciate that you added it in. – Shafik Yaghmour Jun 26 '14 at 21:48
9

All three versions of the standard — ISO/IEC 9899:1990, ISO/IEC 9899:1999 and ISO/IEC 9899:2011 — contain an example in the section with the title External object definitions (§6.7.2 of C90, and §6.9.2 of C99 and C11) which shows:

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

The example continues, but the extern int i3 = 3; line clearly shows that the standard indicates that it should be allowed. Note, however, that examples in the standard are technically not 'normative' (see the foreword in the standard); they are not a definitive statement of what is and is not allowed.

That said, most people most of the time do not use extern and an initializer.

Community
  • 1
  • 1
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278