1

a)The definition of an external variable is same as that of a local variable,ie, int i=2; (only outside all functions). But why is extern int i=2; too working as the definition? Isn't extern used only in variable declaration in other files?

b)file 1

  #include<stdio.h>
  int i=3;
  int main()
  {
      printf("%d",i);
      fn();
  }

file2

  int i;  //  although the declaration should be: extern int i; So, why is this working?
  void fn()
  {
      printf("%d",i);
  }

OUTPUT: 3 in both cases

  • The edit to your question is odd. I don't think you actually copied in the code that you used. For example, your call to `fn()` in file 1 is outside the `main` function! And you mean `int main(void)` rather than `int main()`. – David Heffernan May 04 '12 at 16:41
  • This other doubt also cropped up, so i edited it. And yes, i didn't copy the code, i typed it. Thanks for pointing out the error. It's now correct.And int main() works just fine in my compiler. –  May 04 '12 at 16:56
  • So, any explanation for the second one? –  May 04 '12 at 16:57
  • I've added that to my answer. – David Heffernan May 04 '12 at 17:02

2 Answers2

5

For historical reasons, the rules for determination of linkage and when a declaration provides a definition are a bit of a mess.

For your particular example, at file scope

extern int i = 2;

and

int i = 2;

are equivalent external definitions, ie extern is optional if you provide an initializer.

However, if you do not provide an initializer, extern is not optional:

int i;

is a tentative definition with external linkage, which becomes an external definition equivalent to

int i = 0;

if the translation unit doesn't contain another definition with explicit initializer.

This is different from

extern int i;

which is never a definition. If there already is another declaration of the same identifier visible, then the variable will get its linkage from that; if this is the first declaration, the variable will have external linkage.

This means that in your second example, both file1 and file2 provide an external definition of i, which is undefined behaviour, and the linker is free to choose the definition it likes best (it may also try to make demons fly out of your nose). There's a common extension to C (see C99 Annex J.5.11 and this question) which makes this particular case well-defined.

Community
  • 1
  • 1
Christoph
  • 164,997
  • 36
  • 182
  • 240
  • The examples in the standard contradict this answer. – David Heffernan May 04 '12 at 18:00
  • You explanation seems to agree with what K & R has to say. –  May 04 '12 at 18:00
  • But why should extern int i=2; work when extern is used only in declaration and not in definitions? –  May 04 '12 at 18:03
  • @DavidHeffernan: which examples? – Christoph May 04 '12 at 18:11
  • @rudra: `extern` can be used in definitions - however, if you use `extern`, you only get a definition if you also provide an initializer – Christoph May 04 '12 at 18:12
  • But in a single file program, inside main() extern int i=2; gives the following error: "'i' has both extern and initializer". So it cannot be a valid definition syntax! –  May 04 '12 at 18:39
  • Although it's a valid definition in a multifile program! –  May 04 '12 at 18:42
  • @rudra: the rules for file-scope and block-scope declarations are different -- your particular case is explicitly disallowed by C99 6.7.8 §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.* – Christoph May 04 '12 at 18:42
  • @chirstopher one more thing. If in the second file i replace int i; by i = 3; it gives an error for multiple definitions. How is i=3; definition? –  May 04 '12 at 19:11
  • @Christoph I was mis-reading the standard. The key to this is the common extension. – David Heffernan May 04 '12 at 22:29
1

In C, an extern with an initialization results in a variable being allocated. That is the declaration will be considered a defining declaration. This is in contrast with the more common use of extern.

The C standard says:

6.9.2 External object definitions

.....

If the declaration of an identifier for an object has file scope and an initializer, the declaration is an external definition for the identifier.

As for the second part of your question, your declaration int i at file scope has external linkage. If you want to give it internal linkage you need to declare it static int i. The C standard says:

6.2.2 Linkages of identifiers

......

If the declaration of an identifier for an object has file scope and no storage-class specifier, its linkage is external.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • while it's true that the line `int i;` in file2 provides a declaration with external linkage, it's also a tentative definition; this means both file1 and file2 provide a definition of the same external identifier, which is undefined behaviour! – Christoph May 04 '12 at 17:12
  • @Christoph No, the definition in file1 is not a tentative declaration. – David Heffernan May 04 '12 at 17:13
  • file1 provides an external definition, file2 a tentative definition which also becomes an external definition at end of translation unit – Christoph May 04 '12 at 17:16