2010-05-06 4 views
4

PourquoiC initialisation d'un tableau

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

travail, mais

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

échoue avec SEGV lorsque opcode_str [0] est printf'd?

Je pense que c'est parce que la deuxième liste n'a pas alloué de mémoire pour le tableau de cinq éléments de pointeurs, mais j'ai besoin d'une explication plus complète.

Tout le meilleur,

Chris.

Répondre

10

C'est correct. Essentiellement, vous essayez d'assigner un tableau à un pointeur. GCC 4.4.1 met en garde à ce sujet par défaut:

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

Il répète les éléments excès d'avertissement 4 fois, puisque vous mettez essentiellement 5 pointeurs où un seul s'adaptera. Vous pouvez utiliser gcc -Werror pour forcer tous les avertissements à être des erreurs.

Vous pouvez faire:

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"; 

Mais vous avez déjà trouvé la meilleure façon de le faire. Dans la mesure où l'erreur se produit, une fois que vous invoquez un comportement indéfini, vous ne pouvez vraiment pas compter sur une heure particulière pour que les problèmes se manifestent.

Mais je pense que opcode_str contient un pointeur sur DATA. Donc (en supposant 32 bits) il va essayer d'interpréter les quatre premiers octets à opcode_str ('D', 'A', 'T', 'A') comme les quatre octets d'un char *.

+0

Merci. Pourquoi n'échoue-t-il pas au moment de la compilation ou lorsque le pointeur est initialisé? – fadedbee

+2

@chrisdew il est un comportement indéfini pour violer une règle sémantique en C. La règle que vous violez est * L'initialiseur pour un scalaire doit être une seule expression, facultativement entourée d'accolades. * Cependant, vous avez plusieurs expressions entre accolades. –

+1

Voilà, je laisserais l'avertissement défiler sur mon écran. Doh! Je peux maintenant voir que j'ai mis le pointeur char ** à la valeur du pointeur char * sur "DATA". "DATA" a ensuite été évalué comme si ces quatre octets contenaient un pointeur, ce qui a provoqué le segfault. – fadedbee