3

Answers to the question above don't answer my question. I know what extern does. The question is if we ever need extern. It only seems cleaner to use extern (and compile with -fno-common), but it doesn't seem there are situations when we need it.

Similar questions have already been answered (e.g. here), but this question is a bit different.

Say, I have two files:

file_a.c:

#include <stdio.h>

int sixsixsix = 666;

void lucky_seven();

int main(int argc, char *argv[]){
  printf("%d\n", sixsixsix);
  lucky_seven();
  printf("%d\n", sixsixsix);
  return 0;
}

file_b.c:

int sixsixsix;

void lucky_seven(){
  sixsixsix = 777;
}

I can compile with GCC using gcc -std=c99 file_a.c file_b.c with no errors. The compiled program gives as expected the output:

666
777

I only get errors if I compile with -fno-common. In this case it is necessary to use extern in file_b.c:

file_b.c:

extern int sixsixsix;

void lucky_seven(){
  sixsixsix = 777;
}

Aside from this special case, that is, if I have a compiler which doesn't put multiply declared variables in a common block, is there any other use for extern for variables? Can you give me example code in which extern becomes unavoidable?

Community
  • 1
  • 1
viuser
  • 953
  • 6
  • 19
  • Am I missing something? How do you inform the compiler that you are using a variable defined in another file? – terence hill Jan 10 '16 at 15:34
  • Well, make it *char* in the other source file and consider if you still like what is going to happen. – Hans Passant Jan 10 '16 at 15:44
  • 1
    Possible duplicate of [Why wont extern link to a static variable?](http://stackoverflow.com/questions/2841762/why-wont-extern-link-to-a-static-variable) – bmargulies Jan 10 '16 at 15:51
  • See my answer to http://stackoverflow.com/questions/2841762/why-wont-extern-link-to-a-static-variable/2841771#2841771. – bmargulies Jan 10 '16 at 15:51
  • 1
    @HansPassant: ok, in **file_b.c**, we use `char sixsixsix` and (so that we don't get an overflow) we also use `sixsixsix = 7`. Program compiles successfully, but gives output `666 [linebreak] 519`. So `lucky_seven()` only overwrites the last byte! 666 = 0x29A, which becomes 0x207 = 519. ***I do not like this at all!!!*** Why is `-fno-common` not standard? The standard setting seems to be a source of nasty errors! – viuser Jan 10 '16 at 16:00
  • http://port70.net/~nsz/c/c11/n1570.html#6.2.2p4 – too honest for this site Jan 10 '16 at 16:17

1 Answers1

2

The extern keywords is necessary when your project consist of multiple files and a variable defined in one of the source file is needed in another one.

For example, if you define the variable in source1.c, then you must declare it as extern in source2.c (directly or by including an header file).

Any other file that reference the variable must declare it as extern.

See this post1 for a very very detailed explanation of the use of the extern keyword


EDIT

I was curious and thus continued to search on this topic.

This is the another relevant post2 which is directly addressing your question. And again the answer comes from Jonathan Leaffler.

Here, for sake of completeness, I will report an excerpt of the above question/answer.

The problem raised in the post was specifically: why if you define a variable in two distinct source files the compiler doesn't even rise a warning?

Short answer is that you do not violate any constrain in the Standard and the compiler is free to decide what to do.

Moreover, as shown in post1, it is possible to write a code that actually works, using gcc and clang (and maybe other compilers too).

But why we should bother? We know that is better to use extern! I found very interesting the observation of the OP in post2:

Note: this is important because the question occurs in the context of static analysis. If the two files may refuse to be linked on some platform, the analyzer should complain, but if every compilation platform accepts it then there is no reason to warn about it.


The relevant paragraph of the C standard is:

J.5.11 Multiple external definitions

There may be more than one external definition for the identifier of an object, with or without the explicit use of the keyword extern; if the definitions disagree, or more than one is initialized, the behavior is undefined (6.9.2).

This means that the result is Undefined Behaviour (see also the comment to the post). And, as Jonathan Leffler said:

One of the things that can happen is that the program behaves as you expect; and J.5.11 says, approximately, "you might be lucky more often than you deserve"

Confirmed in the comment by Johannes Schaub:

To be really clear whether it's allowed or not: No it's undefined behavior in C. It's like doing a[10] = 0; even if a is a int a1;


Conclusion

Defining a variable in multiple files is Undefined Behaviour, don't do that unless you are doing some wired test. Use extern!

Community
  • 1
  • 1
terence hill
  • 3,354
  • 18
  • 31
  • (Don't have enough rep to upvote your answer). Ok, so after reading the linked post, especially the "Not so good way to define global variables" part, I would tentatively say that the answer to my question is: "You never *need* `extern`. It is just better to use it." Right? – viuser Jan 10 '16 at 16:25
  • I would say you need it, you can avoid it at your own risk! – terence hill Jan 10 '16 at 16:51
  • Ok, with GCC and CLANG it compiles without using `extern`. It does indeed **not** work with the Tiny C Compiler with standard settings. – viuser Jan 11 '16 at 06:37
  • @VIofSwords please take a look at the updated answer. – terence hill Jan 12 '16 at 00:15
  • @Jonathan Leffler I copied a lot from your posts ;) – terence hill Jan 12 '16 at 00:18
  • after 6 month: what you quoted under "J.5.11 Multiple external definitions" is what makes the behavior in the example in the question *possible*. It is a compiler extension. *Without* that extension it is undefined behavior. And the relevant portion of the standard for that is 6.9/5 of the ISO/IEC 9899-2011 standard. – viuser Aug 07 '16 at 07:40