fadedbee
fadedbee

Reputation: 44739

C array initialisation

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.

Upvotes: 6

Views: 701

Answers (1)

Matthew Flaschen
Matthew Flaschen

Reputation: 284786

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*.

Upvotes: 10

Related Questions