28 votes

Pourquoi puis-je utiliser des pointeurs comme chaînes lorsqu'ils sont déclarés avec des guillemets doubles, mais pas entre accolades, en C?

Si je déclare et utilise un pointeur comme celui-ci:

 int counter;
char *pCow = "pCow goes MOO";

for(counter = 0; counter < 14; counter++)
    printf("%c", pCow[counter]);
 

il affiche la chaîne entière et fonctionne et oui et il y a beaucoup de réjouissances.

Cependant, si j'utilise un initialiseur comme celui-ci:

 int counter;
char *pCow = {'p','C','o','w',' ','g','o','e','s',' ','M','O','O','\0'};

for(counter = 0; counter < 14; counter++)
    printf("%c", pCow[counter]);
 

le programme plante et pCow refuse de moo pour mon plaisir hédoniste!

 3 Warnings. 0 Errors
line 11 (near initialization for 'pCow') [enabled by default]   C/C++ Problem
line 11 excess elements in scalar initializer [enabled by default]  C/C++ Problem
line 11 initialization makes pointer from integer without a cast [enabled by default]   C/C++ Problem
 

Testé avec amour dans Eclipse CDT.

40voto

DaoWen Points 14480

Dans ce cas, pCow est fixé à l'adresse d'un c-string dans la mémoire statique:

char *pCow = "pCow goes MOO";

Dans ce cas, pCow à la valeur 'p' (c'est à dire, 112):

char *pCow = {'p','C','o','w',' ','g','o','e','s',' ','M','O','O','\0'};

Depuis l'adresse 112 plus susceptibles de points limité/mémoire non valide, que les causes de votre programme à sauter lorsque vous essayez d'accéder pCow[counter].

L'avertissement "l'excès d'éléments scalaires initialiseur" est vous dire que c'est ignorer tous les trucs après l' 'p' depuis le pointeur ne nécessite qu'une seule valeur.

L'avertissement "initialisation rend pointeur d'entier sans un cast" est vous dire que vous êtes à l'aide de 'p' comme un pointeur, ce qui n'est probablement pas une bonne idée...

Ce que vous voulez faire est de déclarer pCow comme un tableau de caractères plutôt qu'un pointeur de caractère si vous souhaitez utiliser la syntaxe d'initialiseur:

char pCow[] = {'p','C','o','w',' ','g','o','e','s',' ','M','O','O','\0'};

11voto

Lundin Points 21616

"pCow goes MOO" est un littéral de chaîne et ont deux usages différents. Vous pouvez soit l'utiliser comme un initialiseur d'un tableau:

char aCow[] = "pCow goes MOO";

Auquel cas le contenu de la chaîne littérale sont copiés dans le tableau.

Ou sinon, vous pouvez utiliser une chaîne littérale comme un stand-alone de la constante de la matrice de n'importe où dans votre programme. Par exemple strcpy(cow, "pCow goes MOO");. Donc, il y a une différence notable entre ces deux:

char aCow[] = "pCow goes MOO";
char* pCow  = "pCow goes MOO";

Dans le premier cas, la traduction littérale est copié dans le tableau. Dans le second cas, la traduction littérale reste autonome constante dans la mémoire en lecture seule, qui nous point à l'aide d'un pointeur. L'ancien peut être modifié, mais pas la seconde.

Comme pour le cas de

char *pCow = {'p','C','o','w',' ','g','o','e','s',' ','M','O','O','\0'};

Vous êtes à l'aide d'un pointeur, mais vous n'avez pas un littéral de chaîne. Au lieu de cela vous avez une liste d'initialiseur prévu pour un tableau. Un bon compilateur vous préviens pour "excès de l'initialiseur". La raison que le code compile est une très curieuse règle en C qui permet de plaine de variables initialisées avec des accolades, par exemple int x = {1};. Ainsi, le compilateur utilise cette règle pour initialiser le pointeur de votre souris pour pointer à l'adresse 'p', ce qui est évidemment absurde, et puis il ignore le reste de la liste d'initialiseur.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X