152 votes

C : différences entre pointeur de char et tableau

Tenir compte :

J’ai lu The C Programming Language, 2e édition, que les deux énoncés ci-dessus ne font pas la même chose.

J’ai toujours pensé qu’un tableau est un moyen pratique pour manipuler des pointeurs pour stocker des données, mais ce n’est clairement pas le cas... Quelles sont les différences « non négligeable » entre tableaux et pointeurs en C ?

161voto

John Bode Points 33046

Voici une hypothétique carte mémoire, montrant les résultats des deux déclarations:

                0x00  0x01  0x02  0x03  0x04  0x05  0x06  0x07
    0x00008000:  'n'   'o'   'w'   ' '   'i'   's'   ' '   't'
    0x00008008:  'h'   'e'   ' '   't'   'i'   'm'   'e'  '\0'
        ...
amessage:
    0x00500000:  'n'   'o'   'w'   ' '   'i'   's'   ' '   't'
    0x00500008:  'h'   'e'   ' '   't'   'i'   'm'   'e'  '\0'
pmessage:
    0x00500010:  0x00  0x00  0x80  0x00

La chaîne littérale "c'est maintenant le temps" est stocké comme un 16-élément de tableau de char à l'adresse de mémoire 0x00008000. Cette mémoire peut ne pas être accessible en écriture, il est préférable de supposer qu'il ne l'est pas. Vous ne devriez jamais tenter de modifier le contenu d'une chaîne littérale.

La déclaration

char amessage[] = "now is the time";

alloue un 16-élément de tableau de char à l'adresse de mémoire 0x00500000 et copie le contenu de la chaîne littérale. Cette mémoire est accessible en écriture; vous pouvez modifier le contenu de amessage au contenu de votre coeur:

strcpy(amessage, "the time is now");

La déclaration

char *pmessage = "now is the time";

alloue un seul pointeur de char à l'adresse de mémoire 0x00500010 et copie l' adresse de la chaîne littérale.

Depuis pmessage points de la chaîne de caractères littérale, il ne devrait pas être utilisé comme un argument pour les fonctions qui ont besoin de modifier le contenu de la chaîne:

strcpy(amessage, pmessage); /* OKAY */
strcpy(pmessage, amessage); /* NOT OKAY */
strtok(amessage, " ");      /* OKAY */
strtok(pmessage, " ");      /* NOT OKAY */
scanf("%s", amessage);      /* OKAY */
scanf("%s", pmessage);      /* NOT OKAY */

und so weiter. Si vous avez changé pmessage à point à amessage:

pmessage = amessage;

ensuite, il peut être utilisé partout amessage peut être utilisé.

114voto

Walt W Points 2074

Vrai, mais c'est une différence subtile. Essentiellement, l'ancienne:

char amessage[] = "now is the time";

Définit un tableau dont les membres vivent dans le champ d'application actuel de la pile de l'espace, considérant ce qui suit:

char *pmessage = "now is the time";

Définit un pointeur qui vit dans l'étendue actuelle de l'espace de pile, mais qui fait référence à la mémoire ailleurs (dans celui-ci, "c'est maintenant le temps" est stocké ailleurs dans la mémoire, généralement une chaîne de caractères de la table).

Notez également que, parce que les données appartenant à la deuxième définition (explicite pointeur) n'est pas stocké dans le champ d'application actuel de l'espace de pile, il n'est pas précisé exactement où il sera stocké et ne doivent pas être modifiés.

Edit: Comme l'a souligné Marc, GMan, et Pavel, il y a aussi une différence lorsque l'adresse de l'opérateur est utilisé sur l'un de ces variables. Par exemple, &pmessage retourne un pointeur de type char**, ou un pointeur vers un pointeur de caractères, tandis que les &amessage retourne un pointeur de type char(*)[16], ou un pointeur vers un tableau de 16 caractères (qui, comme un char**, doit être déréférencés deux fois litb points).

14voto

Un tableau contenant les éléments. Un pointeur de points.

La première est une forme abrégée de dire

char amessage[16];
amessage[0] = 'n';
amessage[1] = 'o';
...
amessage[15] = '\0';

C'est un tableau qui contient tous les caractères. L'initialisation spéciale initialise pour vous, et détermine automatiquement la taille. Les éléments du tableau sont modifiables - vous pouvez remplacer les caractères.

La seconde forme est un pointeur, et qu'il suffit de points pour les personnages. Il stocke les caractères qui ne sont pas directement. Depuis le tableau est un littéral de chaîne, vous ne pouvez pas prendre le pointeur et d'écrire à l'endroit où il points

char *pmessage = "now is the time";
*pmessage = 'p'; /* undefined behavior! */

Ce code serait probablement planter sur votre boîte. Mais il peut faire tout ce qu'il aime, parce que son comportement est indéfini.

7voto

Norman Ramsey Points 115730

Je ne peux pas ajouter utilement pour les autres réponses, mais je ferai remarquer que, dans la Profondeur C Secrets, Peter van der Linden, couvre cet exemple en détail. Si vous posant ces questions, je pense que vous allez adorer ce livre.


P. S. Vous pouvez affecter une nouvelle valeur à pmessage. Vous ne pouvez pas affecter une nouvelle valeur à l' amessage; il est immuable.

7voto

Tamás Szelei Points 8660

Si un tableau est défini afin que sa taille soit disponible au moment de la déclaration, `` retournera le nombre d’éléments dans le tableau.

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