1

How does the following example usage of extern specifer behave.

We have a global variable int x both in files one.c and two.c We want to use these in three.c so have declared this variable in three.c as

extern int x;

What would happen when we compile and link these files?

My answer is: compilation of all these files should succeed, however the linker should flag an error at linking, due to multiple declarations of x. Would there be any difference in behavior in C++ ?

Is these any way to refer to int x (in three.c) simultaneously from both files, in C and C++. In C++, I guess we can use namespaces to acheive this. Right?

Jens
  • 69,818
  • 15
  • 125
  • 179
Ankur
  • 11,239
  • 22
  • 63
  • 66
  • The declaration of the variable should be in a header, and the header should be used in each file that references the variable, and it should be used in the one (single, solitary) file that actually defines the variable. If you try to link code with two definitions of a single global variable, you are outside the standard behaviour and into common extensions documented in the standard (Appendix J). – Jonathan Leffler Nov 24 '09 at 16:30
  • See also: http://stackoverflow.com/questions/1433204/what-are-extern-variables-in-c/ – Jonathan Leffler Nov 24 '09 at 16:33

5 Answers5

6

By default, global variables have external linkage, which means that they can be used by other source files (or "translation units"). If you instead declare your global variables with the static keyword, they will have internal linkage, meaning they will not be usable by other source files.

For variables with external linkage, you can't have multiple variables with the same name, or the linker will complain. You can have two variables with the same name, though, as long as at least one has internal linkage, and of course you can't reference both of them in the same source file.

An extern declaration is just saying to the compiler "here is the name of some variable with external linkage defined in another translation unit," allowing you to refer to that variable.

C++ is exactly the same, except for the addition of namespaces. If global variables are put inside a namespace, then they can have the same name without linker errors, provided they are in different namespaces. Of course, all references to those variables then have to either refer to the full name namespace::var_name, or use a using declaration to establish a local namespace context.

C++ also has anonymous namespaces, which are entirely equivalent to using the static keyword for global variables in C: all variables and functions declared inside an anonymous namespace have internal linkage.

So, to answer your original question, you are right -- compilation would succeed, but linking would fail, due to multiple definitions of the variable x with external linkage (specifically, from the translation units one.c and two.c).

From three.c, there is no way to refer simultaneously to both variables x. You'll need to rename x in one or both modules, or switch to C++ and put at least one x inside a namespace.

Adam Rosenfield
  • 390,455
  • 97
  • 512
  • 589
  • How does the linker know which "translation units" to look in for the extern variable, is that some setting or something? – marchinram Oct 15 '10 at 13:41
  • @marchinram: The linker knows because at link time, the linker loads all of the object files and libraries that are being linked into memory at once, and then it goes through them and fixes up extern references. If it finds `var_name` in `a.o` and then sees that `b.o` references `var_name`, it will fix up the placeholders in `b.o` to point to the actual `var_name` in `a.o`. If `var_name` doesn't exist anywhere, that's an error (usually called "unresolved external reference" or somesuch). – Adam Rosenfield Oct 15 '10 at 14:49
  • Adam, I understand what your saying, in that the linker looks in all the object files to resolve externs, but my question is how does it know which files to look in. I normally use an IDE so it probably sets some setting to look in all the files in my project, I just wanted to know if there is a compiler setting or something to set where the linker should look for the files. – marchinram Oct 24 '10 at 11:04
  • @marchinram: The linker looks at the list of files specified in your project. There's a one-to-one mapping between source files in your project (technically *translation units*) and object files that get linked at the end. For makefile-based projects, the names of all the object files are just passed to the linker on the command line. – Adam Rosenfield Oct 24 '10 at 16:48
1

In C, you could do this:

// one.c
static int x;
int *one_x = &x;

// two.c
static int x;
int *two_x = &x;

// three.c
extern int *one_x;
extern int *two_x;

Now you can refer unambiguously to the x in file one.c or the x in file two.c from the file three.c.

However, this might be a bit more effort than it's worth. Perhaps you should be coming up with more descriptive names for your global variables instead of toying around with theoretical ways to circumvent C's single global namespace.

Chris Lutz
  • 73,191
  • 16
  • 130
  • 183
0

To avoid generating duplicate symbols, you should declare extern int x; in a single header file (a .h file), and then have all .c files which will use x #include that header file, and define or initialize int x; in one of the .c files.

Charles Salvia
  • 52,325
  • 13
  • 128
  • 140
  • 1
    That is, assuming there should only be one variable. I think the OP wants two global variables with the same name, which is rather silly, and I assume a theoretical simplification of a more complex flawed design. – Chris Lutz Nov 24 '09 at 04:58
  • Chris this is not too uncommon in production code where you end up using code from a third party vendor or multiple teams working on a product with multiple subsystems. – Ankur Nov 24 '09 at 05:09
  • 1
    The problem is the same: You have two global variables with external linkage with the same name, and you need to use both of them. And the answer is, in C, you can't. In C++ you can with namespaces, but then they don't really have the same name, so why not just give them new names and not have to bother with the hassle in the first place? – Chris Lutz Nov 24 '09 at 05:12
  • Yes. But sometimes, you can't modify these source files (3rd party) without breaking other code as well, so one needs a workaround. – Ankur Nov 24 '09 at 05:21
0

You might be interested by the answers to this question.

Summary: the linker may or may not fail to link the file. It depends on the initialization of the variable. It will definitely fail if the variable has different initializations in different files.

Community
  • 1
  • 1
Pascal Cuoq
  • 79,187
  • 7
  • 161
  • 281
0

Remember that you can NOT extern a global static variable.. !!

Jay D
  • 3,263
  • 4
  • 32
  • 48