Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C array initialisation

Tags:

arrays

c

Why does

static char *opcode_str[] = { "DATA"
                            , "DATA_REQUEST_ACK"
                            , "ACK_TIMER_EXPIRED"
                            , "ACK_UNEXPECTED_SEQ"
                            , "ACK_AS_REQUESTED"
                            } ;

work, but

static char **opcode_str = { "DATA"
                           , "DATA_REQUEST_ACK"
                           , "ACK_TIMER_EXPIRED"
                           , "ACK_UNEXPECTED_SEQ"
                           , "ACK_AS_REQUESTED"
                           } ;

fails with SEGV when opcode_str[0] is printf'd?

I think it's because the second listing has not allocated memory for the five element array of pointers, but I need a more comprehensive explanation.

All the best,

Chris.

like image 235
fadedbee Avatar asked Dec 29 '22 17:12

fadedbee


1 Answers

That's correct. You're essentially trying to assign an array to a pointer. GCC 4.4.1 warns about this by default:

opcode_str.c:4: warning: initialization from incompatible pointer type
opcode_str.c:5: warning: excess elements in scalar initializer

It repeats the excess elements warning 4 times, since you're essentially putting 5 pointers where only one will fit. You can use gcc -Werror to force all warnings to be errors.

You could do:

static char **opcode_str = malloc(sizeof(char *) * 5);
opcode_str[0] = "DATA";
opcode_str[1] = "DATA_REQUEST_ACK";
opcode_str[2] = "ACK_TIMER_EXPIRED";
opcode_str[3] = "ACK_UNEXPECTED_SEQ";
opcode_str[4] = "ACK_AS_REQUESTED";

But you've already found the best way to do it. As far as when the error occurs, once you invoke undefined behavior you really can't count on a particular time for problems to manifest.

But I think opcode_str holds a pointer to DATA. So (assuming 32-bit) it will try to interpret the first four bytes at opcode_str ('D','A','T','A') as as the four bytes of a char*.

like image 158
Matthew Flaschen Avatar answered Jan 26 '23 00:01

Matthew Flaschen