Bad linkage of `char *array[size]` and `extern char **array`?
c, gcc, linkage
Solution
Whenever you use different, incompatible types for the same variable in different compilation units (as you have done here), you get undefined behavior. That means it probably won't work and you may not get any error or warning messages about it.
WHY this happens (and why the spec says this is undefined) is due to the way most linkers work. Most linkers don't understand anything about types; they only understand names and memory. So as far as the linker is concerned, a variable is just a block of memory starting at some address. In your (original) program `main.c` defines `names` as referring to the start of a block of memory big enough to hold 10 pointers (probably 40 or 80 bytes, depending on whether this is a 32-bit or 64-bit system), all of which are NULL. `whaterver.c`, on the other hand, assumes that `names` refers to a block of memory big enough to hold ONE pointer, and that pointer points at an array of 10 pointers.
Problem
First, see this example (I made this up for the sake of example, it's not a real program): whatever.h ``` #ifndef WHATEVER_H #define WHATEVER_H void fill(void); #endif ``` main.c ``` #include <stdio.h> #include "whatever.h" char *names[10] = {NULL}; int main() { int i; fill(); for (i = 0; i < 10; ++i) printf("%s\n", names[i]); return 0; } ``` whatever.c ``` #include "whatever.h" extern char **names; void fill(void) { int i; for (i = 0; i < 10; ++i) names[i] = "some name"; } ``` When I make this program using: ``` gcc -o test main.c whatever.c -Wall -g ``` I don't get any errors or warnings. However, when I run the program, I see that in `fill`, `names` is actually `NULL`. If in `whatever.c` I change ``` extern char **names; ``` to ``` extern char *names[]; ``` then everything is fine. Can anyone explain why this happens? If gcc couldn't link `extern char **names;` with the one in `main.c`, shouldn't it have given me an error? If it could link them, how come `names` ends up being `NULL` in `whatever.c`? Also, how does `extern char **names;` differ from `extern char *names[];`? I am using gcc version 4.5.1 under Linux. Update To further investigate this, I change the definition of `names` in `main.c` to: ``` char *names[10] = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10"}; ``` (keeping `extern char **names;` in `whatever.c`) and with `gdb`, I can see that `names` has a value. If I cast that value to `char *` and print it, it gives me `"1"`. (Note that, it's not `*names` that is `"1"`, but `(char *)names`) Basically, what it means is that gcc has somehow managed to link `extern char **names;` in `whatever.c` with `names[0]` in `main.c`!