Pourquoi ce code génère-t-il des problèmes d'exécution:
char stuff[100];
strcat(stuff,"hi ");
strcat(stuff,"there");
mais ce n'est pas?
char stuff[100];
strcpy(stuff,"hi ");
strcat(stuff,"there");
strcat
cherchera le terminateur null, interprétera cela comme la fin de la chaîne et y ajoutera le nouveau texte, écrasant le terminateur null dans le processus et écrivant un nouveau terminateur nul à la fin de la concaténation.
char stuff[100]; // 'stuff' is uninitialized
Où est le terminateur nul? stuff
n'est pas initialisé, il peut donc commencer par NUL ou ne contenir NUL nulle part.
En C++, vous pouvez faire ceci:
char stuff[100] = {}; // 'stuff' is initialized to all zeroes
Vous pouvez maintenant faire strcat, car le premier caractère de 'stuff' est le null-terminator, il sera donc ajouté au bon endroit.
En C, vous devez toujours initialiser le «matériel», ce qui peut être fait de différentes manières:
char stuff[100]; // not initialized
stuff[0] = '\0'; // first character is now the null terminator,
// so 'stuff' is effectively ""
strcpy(stuff, "hi "); // this initializes 'stuff' if it's not already.
Dans le premier cas, stuff
contient des déchets. strcat
exige que la destination et la source contiennent les chaînes correctes terminées par un zéro.
strcat(stuff, "hi ");
va scanner stuff
pour un caractère '\0'
final, où il commencera à copier "hi "
. S'il ne le trouve pas, il ira à la fin du tableau et de mauvaises choses peuvent se produire de manière arbitraire (c'est-à-dire que le comportement n'est pas défini).
Une façon d'éviter le problème est la suivante:
char stuff[100];
stuff[0] = '\0'; /* ensures stuff contains a valid string */
strcat(stuff, "hi ");
strcat(stuff, "there");
Ou vous pouvez initialiser stuff
à une chaîne vide:
char stuff[100] = "";
qui remplira tous les 100 octets de stuff
avec des zéros (la clarté accrue vaut probablement tout problème de performances mineur).
Strcat ajoute une chaîne à une chaîne existante. Si le tableau de chaînes est vide, la fin de la chaîne ('\0'
) ne sera pas recherchée et une erreur d'exécution sera générée.
Selon la page de manuel Linux, strcat simple est implémenté de cette façon:
char*
strncat(char *dest, const char *src, size_t n)
{
size_t dest_len = strlen(dest);
size_t i;
for (i = 0 ; i < n && src[i] != '\0' ; i++)
dest[dest_len + i] = src[i];
dest[dest_len + i] = '\0';
return dest;
}
Comme vous pouvez le constater dans cette implémentation, strlen(dest)
ne retournera pas la longueur de chaîne correcte à moins que dest
soit initialisé pour corriger les valeurs de chaîne c. Vous pouvez avoir de la chance d'avoir un tableau avec la première valeur de zéro à char stuff[100];
, mais vous ne devriez pas vous en fier.
Parce que stuff
n'est pas initialisé avant l'appel à strcpy
. Après que la déclaration stuff
ne soit plus une chaîne vide, il s’agit de données non initialisées.
strcat
ajoute des données à la fin d'une chaîne - c'est-à-dire qu'elle trouve le terminateur nul dans la chaîne et ajoute des caractères après celle-ci. Une chaîne non initialisée n'est pas garantie d'avoir un terminateur null, donc strcat
est susceptible de planter.
Si vous deviez initialiser stuff
comme ci-dessous, vous pourriez effectuer les opérations suivantes:
char stuff[100] = "";
strcat(stuff,"hi ");
strcat(stuff,"there");