C program multiple definition error during linking time

Hi,

I have the following files:

// file.h

void foo();
int i = 5; // should be just declared as extern int i;

// file1.c

#include <stdio.h>
#include "file.h"

void foo() {
    i = 10;
    printf("%d\n", i);
}

// file2.c

#include <stdio.h>
#include "file.h"

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

When I compiled the above files using gcc compiler, I got the following linker error

gcc -c file1.c
gcc -c file2.c
gcc -o a.out file*.o // linker error: file2.o: multiple definition of 'i'

After searching in the google, I got below links where I found the solution
Solving multiple definition - C++ Forum
multiple definition of 'variable_name'
"multiple definition" error - C++ Forum

Now, I have changed the code in the file.h as:

extern int i;

Now, my question is, if I want to print the value of i before calling the foo() function in the file2.c, what should I do in order to not to end up in the linker error?

// file2.c

#include <stdio.h>
#include "file.h"

i = 20; // treats as an altogether a new definition of i, implicitly adds int keyword before i
int main() {
        i = 20; // multiple definition error
        printf("%d\n", i);
        foo();
        printf("%d\n", i);
}

That implicit declaration looks very cagey to me... I'm not sure it's doing what you think it is. Do a full-fledged int i=20; outside main in file2.c.

You shouldn't need the 'i=20' in main anymore, since it will start at that value when the program's run anyway, but neither will it hurt anything.

#include <stdio.h>
#include "file.h"

void foo() {
    i = 10;
    printf("%d\n", i);
}
#include <stdio.h>
#include "file.h"

int i = 20; // treats as a altogether a new definition of i, implicitly adds int keyword before i
int main() {
        i = 20;
        printf("%d\n", i);
        foo();
        printf("%d\n", i);
}

If you have the "extern int i" declaration in your file.h then I do not see why you would still get the multiple definition error...because the i in file2.c inside main is unrelated to the i in file1.c inside foo which in turn is unrelated to the global i that is defined in file2.c.

You have to look at the way the different variables are setup in the segments to understand the linkages between them. The global i defined in file2.c lies in the data segment and is unrelated to the local i inside main within the file2.c which lies on the stack frame created for main...similarly the local i inside foo of file1.c lies in the stack frame created for foo and is unrelated to the global i or the i that is local to main...let me know if this helps or if i have managed to confuse you even more :wink:

I suspect the multiple definition errors became undefined external errors at some point...

Yes i too suspect that especially since the op hasnt been clear about the entire code...

Your analysis is incorrect. There are no versions of i which are local to a block (function or otherwise). All of those identifiers refer to the same externally-linked, global storage allocation.

Regards,
Alister

Thanks alister, but when you say so then why in file2.c, the identifier 'i' is not referring to the same externally-linked, global storage allocation as how the file1.c does? that is,

#include <stdio.h>
#include "file.h"

int main() {
    printf("%d\n", i); // undefined reference to `_i'
    foo();
    printf("%d\n", i);
} 

Why I have to allocate a memory for i (declaring an int i) in the global scope in file2.c to get rid of this problem?

Don't do the following. Don't try to initialize the external variable outside of a function.

i = 20;
int main() 

Even if it worked, it's extremely confusing. What's the point or advantage, anyway? Do you want to have two external vars with the same name? If you just want to set the value to 20, do it inside a function.

You're lying to the compiler by telling the compiler it exists (extern int i) but not actually instantiating it anywhere. The extern just tells it to look for it somewhere else, but you must instantiate it in one and only one file.

Good point alister...after dotting my i's i realize that all roads lead to the same i...but the op should be educated on how not to write obfuscated code.