J'ai essayé cette morceine de code:

char string_one[8], string_two[8];
printf("&string_one == %p\n", &string_one);
printf("&string_two == %p\n", &string_two);
strcpy(string_one, "Hello!");
strcpy(string_two, "Long string");
printf("string_one == %s\n", string_one);
printf("string_two == %s\n", string_two);

Et j'ai obtenu cette sortie:

&string_one == 0x7fff3f871524
&string_two == 0x7fff3f87151c
string_one == ing
string_two == Long string

Étant donné que la deuxième valeur de longueur de chaîne est supérieure à la taille spécifiée du tableau respectif, les caractères dont les valeurs d'indice sont supérieures à la taille de tableau spécifiée sont stockés dans les octets suivants, qui appartiennent au premier tableau comme le montrent les adresses. Évidemment, la première chaîne est écrasée. Il n'y a aucun moyen que le deuxième tableau puisse contenir toute la chaîne, il est trop gros. Néanmoins, la sortie imprime la chaîne entière. J'ai spéculé pendant un moment et suis arrivé à la conclusion que la fonction printf() continue de sortir les caractères des octets suivants jusqu'à ce qu'elle rencontre un terminateur de chaîne '\0'. Je n'ai trouvé aucune confirmation pour ma réflexion, alors la question est de savoir si ces spéculations sont correctes?

1
Kaiyaha 16 sept. 2020 à 01:15

3 réponses

Meilleure réponse

À partir du standard C (5.2.1 Jeux de caractères)

2 Dans une constante de caractère ou littéral de la chaîne, les membres de l'ensemble de caractères d'exécution doivent être représentés par les éléments correspondants du jeu de caractères source ou par des séquences d'échappement constituées de la barre oblique inverse, suivie d'un ou plusieurs caractères. Un octet avec tous les bits réglés sur 0, appelé le caractère null,

Et (7.21.6.1 La fonction fprintf)

8 Les spécificateurs de conversion et leurs significations sont:

S Si aucun modificateur de longueur de L est présent, l'argument doit être un pointeur à l'élément initial d'un tableau de type de caractère.273) Les caractères de la matrice sont écrits (mais non compris) le caractère null de terminaison.

3
Vlad from Moscow 15 sept. 2020 à 22:26

Mon compilateur (GCC) dit:

avertissement: ‘__builtin_memcpy’ l’écriture de 12 octets dans une région de taille 8 déborde la destination [-Wstringop-overflow =] strcpy (string_two, "Long string");

0
bekici 15 sept. 2020 à 22:28

Et juste pour montrer comment les optimisations prendront tout ce que vous pensez que vous savez et allumez-la sur sa tête, voici ce qui se passe si vous compilez cela sur un PowerPC PowerPC 64 bits (AKA non X86) avec {{x0}}

$ ./char-array-overlap
&string_one == 0x7fffc502bef0
&string_two == 0x7fffc502bef8
string_one == Hello!
string_two == Long string

Parce que si vous regardez le code machine, il n'exécute jamais du tout strcpy.

0
Zan Lynx 15 sept. 2020 à 23:19