3 votes

Pourquoi le dernier indice d'un tableau de chaînes ne s'imprime-t-il pas en C ?

Je suis curieux de savoir pourquoi le dernier élément de mon tableau de taille 29 est 27, et non 28 ? Pourquoi y a-t-il un espace vide lorsque j'essaie d'imprimer l'objet à la 28e place ? s devrait être le dernier objet à la 28e place, non ?

#include <stdio.h>

int main(void) {
    char strArray[] = { "Jonsnow from Game of Thrones" };
    int lastElem = sizeof(strArray);

    printf("%s\n", strArray);
    printf("Size of array is: %d\n", sizeof(strArray));
    printf("first array value: %c \n", strArray[0]);
    printf("last array value: %c \n", strArray[lastElem - 1]);
    printf("last array value: %c \n", strArray[lastElem - 2]);

    return 0;
}

Sortie :

Jonsnow from Game of Thrones
Size of array is: 29
first array value: J
last array value:
last array value: s

3voto

chqrlie Points 17105

Le dernier octet d'une chaîne de caractères en C est le terminateur nul, un octet dont la valeur est 0 , également écrit comme '\0' . strArray es un char initialisé à partir d'une constante de chaîne de caractères C, sa taille est exactement celle de l'initialisateur, y compris l'octet nul. strArray[lastElem-1] est l'octet nul '\0' .

Sortie d'un octet nul avec printf %c devrait fonctionner correctement, un octet nul étant écrit dans le format stdout mais il est possible que votre terminal ignore de tels octets et produise la sortie que vous avez affichée. Vous pouvez essayer de rediriger la sortie de votre programme vers un fichier et examiner ce fichier avec un éditeur hexagonal pour voir s'il contient effectivement un octet nul avant la nouvelle ligne.

J'obtiens le même comportement sur mon MacBook avec OS/X :

chqrlie@mba1 ~/dev/stackoverflow > ./nullbyte
Jonsnow from Game of Thrones
Size of array is: 29
first array value: J
last array value:
last array value: s

Mais voici le fichier binaire de la sortie du programme :

chqrlie@mba1 ~/dev/stackoverflow > ./nullbyte | od -bc
0000000   112 157 156 163 156 157 167 040 146 162 157 155 040 107 141 155
           J   o   n   s   n   o   w       f   r   o   m       G   a   m
0000020   145 040 157 146 040 124 150 162 157 156 145 163 012 123 151 172
           e       o   f       T   h   r   o   n   e   s  \n   S   i   z
0000040   145 040 157 146 040 141 162 162 141 171 040 151 163 072 040 062
           e       o   f       a   r   r   a   y       i   s   :       2
0000060   071 012 146 151 162 163 164 040 141 162 162 141 171 040 166 141
           9  \n   f   i   r   s   t       a   r   r   a   y       v   a
0000100   154 165 145 072 040 112 040 012 154 141 163 164 040 141 162 162
           l   u   e   :       J      \n   l   a   s   t       a   r   r
0000120   141 171 040 166 141 154 165 145 072 040 000 040 012 154 141 163
           a   y       v   a   l   u   e   :      \0      \n   l   a   s
0000140   164 040 141 162 162 141 171 040 166 141 154 165 145 072 040 163
           t       a   r   r   a   y       v   a   l   u   e   :       s
0000160   040 012
              \n
0000162

Comme vous pouvez le constater, la quatrième ligne contient un octet nul entre les espaces.

Notez également qu'il y a un bogue dans le programme : %d peut être inapproprié pour un argument de type size_t . Le format C99 est le suivant %zu mais pour la portabilité sur des systèmes avec un support d'exécution C99 médiocre, je recommanderais ceci :

printf("Size of array is: %lu\n", (unsigned long)sizeof(strArray));

2voto

Spinkoo Points 2192

LastElem-1 est réservé à l'élément ' \0 ' qui est le terminateur nul.

Le terminateur nul n'imprime rien car il s'agit d'une sentinelle qui indique la fin de la chaîne, car s'il n'y a pas de terminateur nul, étant donné un tableau de caractères, il n'est pas clair où la chaîne se termine.

2voto

Govind Parmar Points 769

Lorsque vous initialisez un tableau de char [] avec une chaîne de caractères entre guillemets, vous ne voyez pas que le terminateur null est ajouté implicitement à la fin de la chaîne. C'est pourquoi le tableau a une longueur de 29 alors que votre chaîne littérale ne comporte que 28 caractères imprimables.

1voto

dbush Points 8590

Lorsque vous initialisez un char avec une constante de chaîne sans donner de taille au tableau, la taille du tableau est le nombre de caractères de la constante de chaîne, plus 1 pour l'octet de fin nul .

Donc strArray[lastElem-1] a une valeur de 0, et l'impression de cette valeur sous forme de caractère n'aboutit généralement à rien.

Si vous utilisez strlen au lieu de sizeof vous obtiendrez 28 et strArray[lastElem-1] serait 's' .

1voto

D3PSI Points 25

C'est parce que dans une chaîne C (un tableau de caractères), la dernière position est une terminaison nulle : ' \0 ' est utilisé pour terminer une chaîne C. Vous n'obtiendrez donc aucun résultat si vous essayez d'imprimer le dernier indice. Le dernier élément de la chaîne actuelle est donc la taille du tableau - 2, comme vous pouvez le voir dans votre résultat.

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