Reputation: 448
I am trying to create a struct in a header file, and initialize a template struct. For some reason, when including the header file in multiple files, it gives me the following error:
gcc foo.c bar.c -o foo -Wall
duplicate symbol _MYFOO in:
/var/folders/s4/zyw5lgk92wj9ljnsypgwdccr0000gn/T/foo-52f8fc.o
/var/folders/s4/zyw5lgk92wj9ljnsypgwdccr0000gn/T/bar-6dc21f.o
ld: 1 duplicate symbol for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
These are my files:
Bar.c
:
#include "bar.h"
#include <stdio.h>
void helloWorld() {
printf("Hello world\n");
}
Bar.h
typedef struct Foo Foo;
struct Foo {
int number;
} MYFOO = {2};
void helloWorld(void);
Foo.c
#include "bar.h"
int main() {
helloWorld();
}
Interestingly enough, when I remove the line containing
MYFOO = {2};
The code compiles and works perfectly fine. I believe it has to do with including Bar.h twice, which ends up including that struct twice? But how would I avoid something like that?
Thank you!
Upvotes: 2
Views: 1685
Reputation: 448
After toying around some more, I found the reason for the error coming from the line MYFOO = {2};
It had to do with the fact that I was initializing the struct in my header file.
Header files are meant for definitions, not initializations.
Instead, the solution for the problem was to simply define and initialize the line in the corresponding source file Foo.c
.
Now, in that file I included as a global variable:
Foo MYFOO = {2};
Now to access this variable in any other file, such as in my Bar.c
, all I needed to do was include the line,
extern Foo MYFOO;
This solved my problem for compilation and meant that I could use the struct in other files as desired!
Upvotes: 1
Reputation: 948
You could add a directive to the Bar.h file to check if the file has already been included:
#ifndef _BAR_H_INCLUDED_
// Bar.h not included - declare your structs, etc, here.
// Define _BAR_H_INCLUDED_ to indicate this file has already
// been included
#define _BAR_H_INCLUDED_ 1
#endif
This should at least prevent you including Bar.h
multiple times.
EDIT
A better solution might be to include the Bar.c
from within the Bar.h
:
// Bar.h
#ifndef _BAR_C_INCLUDED_
// code here
// Include Bar.c
#include "Bar.c"
#define _BAR_C_INCLUDED_
#endif
You can then simply include Bar.h
in your Foo.c
:
// Foo.c
#include <stdio.h>
#include <stdlib.h>
#include "Bar.h"
int main() {
//...
Then to compile:
gcc Foo.c -o Foo
So - here is your updated code - first, Bar.h
#ifndef _BAR_C_INCLUDED_
typedef struct Foo Foo;
struct Foo {
int number;
} MYFOO = {2};
void helloWorld (void);
#include "Bar.c"
#define _BAR_C_INCLUDED_
#endif
Now Bar.c
:
void helloWorld() {
printf("Hello world\n");
}
Lastly, Foo.c
- include stdio.h
here as well as Bar.h
(which will, in turn, include Bar.c
for us):
#include <stdio.h>
#include "bar.h"
int main() {
helloWorld();
}
And to compile:
gcc Foo.c -o Foo -Wall
Upvotes: 3