6

I am unable to understand why this doesn't work.

extern int i;

int main()
{
  printf(" %d ", i);  
}

static int i =3;

Also, this doesn't work:

extern int i;

static int i =3;

int main()
{
  printf(" %d ", i);  
}

But if static variable is defined before the extern declaration it works:

static int i =3;

extern int i;

int main()
{
  printf(" %d ", i);  
}

As I understand from extern int itells that i is present somewhere else and here how it looks lik(int i)

But, somewhere else means:

1) Maybe, later point in the same translation unit as a global variable.

2) Maybe, in some other translational unit.

I was thinking that (1) would be valid even though static int i = 3 has restricted i's scope to the current translation unit where it is defined.

Isn't static int i =3 global( i mean atleast it is visible in the translation unit) here even though it has the restricted scope to its translation unit? Then why isn't compiler unable to find it?

When I compile the first two versions I get the following compile time error:

 error: static declaration of ‘i’ follows non-static declaration
 note: previous declaration of ‘i’ was here

I am unable to understand this error message. Also, why it is complaining it as a static declaration isn't it a definition also?

Yu Hao
  • 119,891
  • 44
  • 235
  • 294
Uchia Itachi
  • 5,287
  • 2
  • 23
  • 26
  • What exactly "doesn't work" ? Is it a compilation issue ? Runtime issue ? I'm compiling your code with VS 2010 and it seems to be working properly. – Nbr44 Aug 09 '13 at 07:47
  • GCC comipler, i get a compile time error static declaration of i follows non-static declaration. – Uchia Itachi Aug 09 '13 at 07:50

3 Answers3

6

C11 6.2.2 Linkages of identifiers Section 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.

So the second declaration will follow the first, back to your examples, the 1st and 2nd example i will have an extern storage-class. The compiler thinks that's an error.

While in the 3rd example, i will be static because static shows first. That should be no problem.

And, in the Section 7 of C11 6.2.2 Linkages of identifiers

If, within a translation unit, the same identifier appears with both internal and external linkage, the behavior is undefined.

So it's better not to declare the same variable with both static and extern in the same translation unit.

Yu Hao
  • 119,891
  • 44
  • 235
  • 294
  • Yes, I agree. But still what worries me is that why the `3`rd version `always` works? Across many compilers. – Uchia Itachi Aug 09 '13 at 09:19
  • @UchiaItachi: Why are you worried about the third version? This answer quotes text from the C standard that explains it: When an `extern` declaration follows a declaration with internal (`static`) or external linkage, the prior declaration is used. – Eric Postpischil Aug 09 '13 at 10:01
  • @UchiaItachi For one thing, even if you tested all the compilers which clearly you can't, and it all works, that doesn't mean it's defined behavior. The standard is the one to decide. – Yu Hao Aug 09 '13 at 10:39
2

Well, a variable is either extern or static. Remember that static at a global level restricts its visibility only to the current translation unit, whereas extern dictates that it is visible across different translation units.

Nobilis
  • 7,310
  • 1
  • 33
  • 67
  • I know that `static` rescrits the visibility and `extern` can dicate across other translation units `including` the current one. But the code works if I define the static variable before and give an extern declaration proving that it has `static` and `extern`. – Uchia Itachi Aug 09 '13 at 07:52
  • This has actually really had me stumped, but my only explanation is the error message itself: `static declaration of ‘i’ follows non-static declaration`. As I understand it `static` must precede any non-static declaration. And by the time `extern` is reached, there already is a definition of `i` that `extern` is happy with. – Nobilis Aug 09 '13 at 08:19
0

It makes no sense to declared something as static and again as extern. Doing so is undefined behaviour, so don't do it.

Jacob Pollack
  • 3,703
  • 1
  • 17
  • 39
  • But isn't why `extern` declaration is there for? To tell that it is defined further down the file? And I know that your code works as I have already mentioned in my question. – Uchia Itachi Aug 09 '13 at 07:54
  • @UchiaItachi, edited my answer, it is correct now. It's undefined behaviour. – Jacob Pollack Aug 09 '13 at 08:40