"bill" <bi**********@gmail.com> writes:
I'm not sure if this belongs in comp.lang.c or in a compiler group, but
I'm experiencing some confusion. Consider:
[tmp]$ cat a.c
const char t[]={0xef, 0xbe, 0xad, 0xde};
const char *a=t;
int bar(void);
int
main()
{
return bar();
}
[tmp]$ cat b.c
extern const char *t;
int
bar(void)
{
return t[0];
}
[tmp]$ gcc -c b.c
[tmp]$ gcc a.c b.o
[tmp]$ ./a.out
Segmentation fault
Looking at the running process through gdb, we see that the segfault
occurs because the attempt to reference t[0] in bar attempts to
dereference the address 0xdeadbeef, which is an illegal address. If
we replace 't' with 'a' in baz, everything works fine. I'm trying to
understand the proper way to initialize constant arrays that are used
accross multiple files (don't want to define them as static as I end up
with multiple copies in the a.out, which I suppose is compiler
dependent and gcc is not doing the right thing with -fmerge-constants
(well, I called it as -Os, and my reading of the man page is that this
implies -fmerge-constants)).
Any insight appreciated.
The reason your program isn't working is that, in a.c, you
declare/define 't' with
const char t[]=...;
which is to say t is declared to be an array, and then in
b.c you declare 't' with
extern const char *t;
which is to say t is declared to be a pointer. The mismatch
of types -- array in one case, pointer in another -- causes
inappropriate code to be generated that accesses the array
't' as though it were a pointer. The result is what you
see.
To fix the problem, declare 't' in b.c as an array rather
than a pointer:
extern const char t[];
If you don't understand the difference between arrays and
pointers, then you need to do some more reading; but I'm
guessing you understand enough to know that they are
different. The declaration 'char t[];' declares an array,
and the declaration 'char *t;' declares a pointer. These
types are not "compatible", to use the technical term of the
Standard, and when used together in different compilation
units this way will usually cause problems.
To add to the confusion, when a variable is a function
parameter, a declaration like
int foo( char name[] ){ ... }
says that the parameter 'name' is a *pointer* rather than an
array: an array-like declaration is changed into a pointer
type in a function parameter context. But that rule applies
only for function parameters, not to variables declared at
the top level (or anywhere besides parameters, for that
matter).