29

I have many different 3 axis sensors I am writing test code for. In the C files for each of them, I have the same char string defined:

char axis[3][8] = {"X", "Y", "Z"}

which I use when I "for" loop results to print the axis that is failing like this:

DEVICETEST_LOG("%s Failed %s axis for Min range\n",device_name[DUT], axis[i]);

I was thinking to save some space I could define a character string array in a header file to use all over the place.

I have tried a number of things, but I can't seem to get an array of strings defined in my header file that I can iterate through to pass a compile.

nbro
  • 15,395
  • 32
  • 113
  • 196
user1054210
  • 481
  • 1
  • 5
  • 11

5 Answers5

42

If you must put it in a header file, use extern or static:

// option 1
// .h
extern char axis[3][8];

// .c
char axis[3][8] = { "X", "Y", "Z" };

// option 2
// .h
static char axis[3][8] = { "X", "Y", "Z" };

Extern tells the linker that there is a global variable named axis defined in one of our implementation files (i.e. in one .c file), and I need to reference that here.

static, on the other hand, tells the compiler the opposite: I need to be able to see and use this variable, but don't export it to the linker, so it can't be referenced by extern or cause naming conflicts.

nbro
  • 15,395
  • 32
  • 113
  • 196
Richard J. Ross III
  • 55,009
  • 24
  • 135
  • 201
  • 1
    Note that, when using `static` and compiling with `-Wunused`, if you do not use that array in that compilation unit, you''get a warning about it. – Victor Mar 23 '21 at 21:37
27

In order to avoid linker errors, you have to declare your array as extern in a header file, and then define the array once in one of your code modules.

So for instance:

//myheader.h
extern const char* axis[3];

then in another code module somewhere:

//myfile.c
const char* axis[3] = { "X", "Y", "Z" };
Jason
  • 31,834
  • 7
  • 59
  • 78
  • 1
    ah that makes sense but seems bassackwards... So the header file I include everywhere points all the other C files to the "myfile.c" local definition. – user1054210 Feb 08 '12 at 16:04
  • So even though I have included the header file in the other c files I am getting a compile error "undefined refrence". So in myheader.h I have >>extern char* AXIS[3][8]; and in myfile.c I have >>char* AXIS[3][8] = {{"X"}, {"Y"}, {"Z"}}; and I am including the myheader.h in the otherfile.c. I also tried a few other tricks but they are not synching up. – user1054210 Feb 08 '12 at 16:52
  • Something else is wrong then because this does work ... what happens if you take the macro out of the equation and simply try to access the array in another code module that includes the header file? Secondly, it should only be `const char* AXIS[3] = { "X", "Y", "Z" };` since these are string literals ... where are you getting the `8` from? – Jason Feb 08 '12 at 17:06
  • I have the 8 there because I get a compile error otherwise. The compiler claims "error: format'%s' expects 'char *' but argument 5 has type 'int'" on the print line basically stateing the assignment of axis[i] to %s is wrong because it is an int even though it is defined as a char. – user1054210 Feb 08 '12 at 17:27
  • By the way ...DUHH that is so stupid of me...why have it in a header file. Just make a global in the high level test file that calls all of the low level files that is extern defined in the low level files. I did not have enough coffee yet when I was thinking this through. – user1054210 Feb 08 '12 at 17:34
7

Add this to your header:

extern char *axis[];

Add this to one source file in your project:

char *axis[] = { "X", "Y", "Z", "Time", "Space", "The Scary Door" };
Robᵩ
  • 163,533
  • 20
  • 239
  • 308
  • Well done! I use this when I need to create a menu' with indefinite number of elements. It's perfect because at compile time the compiler sets up the array length exactly, moreover the code seems to be much more readable. – b3h3m0th Dec 19 '15 at 17:35
3

Put this in your header file

extern char axis[3][8];

and keep this in a C file:

char axis[3][8] = {"X", "Y", "Z"};
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
0

Michael Barr (Netrino) advises against the declaration of storage in a header file. Likewise, the Netrino embedded system coding standard does not condone the use of extern'ed storage in headers.

I generally agree with these principles, and I've found it to be a good idea to extern storage into the C files that need it, and only those.

Throwback1986
  • 5,887
  • 1
  • 30
  • 22