2010-08-13 8 views
7

Pourquoi le code suivant est-il illégal?chaîne littérale dans c

typedef struct{ 
    char a[6]; 
} point; 

int main() 
{ 
    point p; 
    p.a = "onetwo"; 
} 

Cela a-t-il quelque chose à voir avec la taille du littéral? ou est-il simplement illégal d'assigner un littéral de chaîne à un tableau char après qu'il a été déclaré?

+0

double possible de [Affectation des chaînes à des tableaux de caractères] (http://stackoverflow.com/questions/579734/assigning-strings-to-arrays-of-characters) –

+0

Pas tout à fait un doublon, parce que c'est une structure contenant un tableau de caractères, qui est subtilement différent d'un simple tableau de caractères, je l'ai expliqué dans ma réponse. – dreamlax

Répondre

11

Cela n'a rien à voir avec la taille. Vous ne pouvez pas affecter une chaîne littérale à un tableau char après sa création - vous ne pouvez l'utiliser qu'au moment de la définition.

Lorsque vous

char a[] = "something"; 

il crée un tableau de taille suffisante (y compris le nul final) et copie la chaîne au tableau. Il n'est pas recommandé de spécifier la taille du tableau lorsque vous l'initialisez avec un littéral de chaîne. Il se peut que vous ne comptabilisiez pas le caractère nul.

Lorsque vous faites

char a[10]; 
a = "something"; 

vous essayez d'affecter à l'adresse du tableau, ce qui est illégal.

EDIT: comme mentionné dans les autres réponses, vous pouvez faire un strcpy/strncpy, mais assurez-vous que le tableau est initialisé avec la longueur requise.

strcpy(p.a, "12345");//give space for the \0 
6

Vous ne pouvez jamais affecter à des tableaux après qu'ils ont été créés; ceci est également illégal:

int foo[4]; 
int bar[4]; 
foo = bar; 

Vous devez utiliser des pointeurs ou affecter un index du tableau; cela est légal:

p.a[0] = 'o'; 

Si vous voulez laisser un tableau dans la struct, vous pouvez utiliser une fonction comme strcpy:

strncpy(p.a, "onetwo", 6); 

(notez que le tableau de caractères doit être assez grand pour maintenir le terminateur NUL trop, vous voulez probablement faire char a[7] et changer le dernier argument de strncpy à 7)

+1

Je suppose que je devrais être flatté que chaque réponse éditée dans ma solution 'strcpy' –

+0

Ici, avoir un +1. Je voudrais +2 si je le pouvais, mais je trouve un peu étrange que personne n'ait encore remarqué qu'il s'agit d'un 'struct' contenant un tableau, pas seulement un tableau simple. – dreamlax

+0

Bien sûr, "strncpy" vient avec ses propres problèmes, contrairement à la plupart des autres fonctions "n". –

6

les tableaux sont non modifiable lvalues. Donc vous ne pouvez pas les assigner. Le côté gauche de l'opérateur d'affectation doit être un modifiable lvalue.

Toutefois, vous pouvez initialiser un tableau lorsqu'il est défini.

Par exemple:

char a[] = "Hello World" ;// this is legal 
char a[]={'H','e','l','l','o',' ','W','o','r','l','d','\0'};//this is also legal 

//but 

char a[20]; 
a = "Hello World" ;// is illegal 

Cependant, vous pouvez utiliser strncpy(a, "Hello World",20);

+2

Il serait plus clair si vous utilisiez le terme correct 'initialize' au lieu de 'assign' quand un tableau est 'défini' (plutôt que 'déclaré'). –

+2

@Jonathan: Oui, vous êtes pédantically correct. Fixé! :) –

1

Notez que pour stocker la chaîne « onetwo » dans votre tableau, il doit être d'une longueur [7] et non comme écrit dans la question. Le caractère supplémentaire sert à stocker le terminateur '\ 0'.

3

Comme d'autres réponses l'ont déjà fait remarquer, vous ne pouvez initialiser qu'un tableau de caractères avec une chaîne littérale, vous ne pouvez pas affecter une chaîne littérale à un tableau de caractères. Cependant, les structs (même ceux qui contiennent des tableaux de caractères) sont une autre marmite de poisson.

Je ne recommanderais pas de le faire dans un programme réel, mais cela démontre que bien que les types de tableaux ne puissent pas être assignés, les structures contenant des types de tableaux peuvent l'être.

typedef struct 
{ 
    char value[100]; 
} string; 

int main() 
{ 
    string a = {"hello"}; 
    a = (string){"another string!"}; // overwrite value with a new string 
    puts(a.value); 

    string b = {"a NEW string"}; 
    b = a; // override with the value of another "string" struct 
    puts(b.value); // prints "another string!" again 
} 

Ainsi, dans votre exemple original, le code suivant doit compiler correctement:

typedef struct{ 
    char a[6]; 
} point; 

int main() 
{ 
    point p; 

    // note that only 5 characters + 1 for '\0' will fit in a char[6] array. 
    p = (point){"onetw"}; 
} 
+0

+1 pour les exemples 'struct', mais notez que ces littéraux composés sont une addition C99. (Idem pour le commentaire de style '//'.) – schot

1

Pas strcpy ou C99 compund littérale est nécessaire. L'exemple en C ANSI pur:

typedef struct{ 
    char a[6]; 
} point; 

int main() 
{ 
    point p; 
    *(point*)p.a = *(point*)"onetwo"; 
    fwrite(p.a,6,1,stdout);fflush(stdout); 
    return 0; 
} 
Questions connexes