-1

I know this question has been asked many times but mine is a little different, or so I like to think.

So I have a .h file I am using for macros and struct definitions and what not. I do have it guarded with the usual...

#ifndef DEFINITIONS_H
#define DEFINITIONS_H

#define some_macro ....

enum TYPE {.,.,.,.,};

typedef struct Blah{
    ...
    ...
}Blah_t;

#endif

...and this has worked perfectly fine until I tried to add an array

unsigned char EBCDICtoASCIItable[256] = {... , ... blah blah blah };

Which gets the compile errors: multiple definition of 'EBCDICtoASCIItable', first defined here -> main.o:(.data+0x0)

All of my other header files have the appropriate guards. My .h files only include the necessary .h files. My .c files only include their respective .h file, followed by standard libraries.

The weird thing is I have four sets of .h/.c files that use my definitions.h file and I do not include it in my main.c. Yet, I get four complaints of it already being defined in main.o.

Here is my makefile if that helps...

cbase_deux : main.o fileio.o utilities.o cfgFileManager.o communication.o
        gcc -o cbase_deux -g main.o fileio.o utilities.o cfgFileManager.o communication.o

main.o : main.c
        gcc -Wall -pedantic -c main.c -g
fileio.o : fileio.c
        gcc -Wall -pedantic -c fileio.c -g
utilities.o : utilities.c
        gcc -Wall -pedantic -c utilities.c -g
cfgFileManager.o : cfgFileManager.c
        gcc -Wall -pedantic -c cfgFileManager.c -g
communication.o : communication.c
        gcc -Wall -pedantic -c communication.c -g
clean :
        rm cbase_deux main.o fileio.o utilities.o cfgFileManager.o communication.o
Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
JoeManiaci
  • 435
  • 3
  • 15
  • The array is defined once per translation unit (basically every source file you tell gcc to compile). It is only allowed to be defined once. You must define it in exactly one translation unit and only declare it in the header, or make it a proper array of `const unsigned char`. – chris Jul 21 '14 at 16:32

1 Answers1

3

The very same question has been asked many times before. Yours is no different at all.

Include guards have absolutely nothing to do with preventing multiple definitions of entities with external linkage. It is a completely different story. The problem you are having is completely unrelated to include guards.

You defined EBCDICtoASCIItable in a header file as an object with external linkage. And then you included that header into many translation units. That produced multiple definitions of EBCDICtoASCIItable, which triggered linker error.

Don't attempt to define entities with external linkage (objects or functions) in header files. It won't work. Include guards will not help you to make it work. Place a mere declaration of your array in the header file

extern unsigned char EBCDICtoASCIItable[256];

and move the definition into some (one and only one) implementation file

unsigned char EBCDICtoASCIItable[256] = {... , ... blah blah blah };
AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765