5

I'm having two .c files: A1.c and A2.c

A1.c as follows:

int i=0;
void main()
{}

A2.c as follows:

int i=0;
void func()
{}

It compiles well but when I try to link these two .o files, there is a "multiple definition of i" error. I understand i is a global variable here, but doesn't it need an extern keyword to be used in other files. And in my project I'm not using the extern. So how come I get an error?

Rüppell's Vulture
  • 3,583
  • 7
  • 35
  • 49
henryyao
  • 1,758
  • 6
  • 23
  • 37
  • "it need an extern keyword to be used in other files"--Well henry, the default storage class of a global variable is "extern".So you don't need to mention that in A1.c.But you use that in A2.c as that says that the definition of that variable is in another file,ie, A1.c. – Rüppell's Vulture Apr 16 '13 at 14:28
  • @SheerFish What I have learnt is that extern is default for functions, but not for the global variables. – henryyao Apr 16 '13 at 17:33
  • Global variables have extern storage class by default.Here's a StackOverflow link where it has been explained in detail http://stackoverflow.com/questions/4239834/global-variable-in-c-are-static-or-not – Rüppell's Vulture Apr 16 '13 at 18:32
  • What I mean is, it's true for both functions and global variables,not just functions.To quote from the C99 standard "5) If the declaration of an identifier for a function has no storage-class specifier, its linkage is determined exactly as if it were declared with the storage-class specifier extern. If the declaration of an identifier for an object has file scope and no storage-class specifier, its linkage is external." – Rüppell's Vulture Apr 16 '13 at 18:36

4 Answers4

7

At compile time, the compiler exports each global symbol to the assembler as either strong or weak, and the assembler encodes this information implicitly in the symbol table of the relocatable object file. Functions and initialized global variables get strong symbols. Uninitialized global variables get weak symbols.

Given this notion of strong and weak symbols, Unix linkers use the following rules for dealing with multiply defined symbols:

Rule 1: Multiple strong symbols are not allowed.
Rule 2: Given a strong symbol and multiple weak symbols, choose the strong symbol.
Rule 3: Given multiple weak symbols, choose any of the weak symbols.

Your code, A1.c as follows:

int i=0; // Strong Symbol
void main() {}

A2.c as follows:

int i=0; // Strong symbol
void func() {}

As per Rule 1 this is not allowed.

For more detailed information: http://www.geeksforgeeks.org/how-linkers-resolve-multiply-defined-global-symbols/

max
  • 1,509
  • 1
  • 19
  • 24
Nash
  • 88
  • 1
  • 4
6

Long story short, a statement like

extern int i;

is a declaration, while the statement

int i=0;

is a definition.

In C you can declare a variable many times in a program, but you can define it only once.The first statement signifies to A2 that the definition of the variable i is in another file.For one I can't understand why you are so apprehensive about using "extern".

Rüppell's Vulture
  • 3,583
  • 7
  • 35
  • 49
3

In C, a global variable can be accessed from another compilation unit as long as this other compilation unit sees that it exists, by declaring it extern. The linker makes the job have linking the extern declaration and the definition in another .c.

If you want it to be only visible to the .c that you are compiling, you must specify it as static

static int i = 0;
J_D
  • 3,526
  • 20
  • 31
  • "If you want it to be only visible to the .c that you are compiling"----That's not what he intends to do.He is confused why he is getting an error if he uses the statement "int i=0" in those two files A1 and A2 even if he assigns the same value to i. – Rüppell's Vulture Apr 16 '13 at 14:20
  • Ok, I might have misunderstood. I thought that he wanted to use global variables with the same name in multiple .c – J_D Apr 16 '13 at 14:45
  • Well,the suggestion about "static" that you gave will surely help him if and when he intends to do that. – Rüppell's Vulture Apr 16 '13 at 14:48
-1

Of course it fails on the link: it tries to combine two object files that reference an object at two different memory locations.

In such cases, the real definition of your variable must be UNIQUE across all your source code, and all other references to this variable must be done through the use of the external keyword (as you sat).

The compilation doesn't whine because it doesn't know the relationship of your two files, only the linker has to figure that out.

Gui13
  • 12,993
  • 17
  • 57
  • 104