2016-12-08 2 views
2

Je lis this document, il dit:c strncpy ou non nulle fin

char *strncpy(char *destination, const char *source, size_t num); 

caractères Copier de chaîne Copies les premiers caractères de numsource à destination. Si la fin de la chaîne C source (qui est signalée par un caractère nul) est trouvée avant que les caractères num aient été copiés, destination soit complétée avec des zéros jusqu'à ce qu'un total de num caractères lui ait été écrit.

Aucun caractère nul n'est implicitement ajouté à la fin de la destination si la source est plus longue que num. Ainsi, dans ce cas, destination ne doit pas être considéré comme une chaîne C terminée par un caractère nul (la lire en tant que telle débordera).

destination et source ne doit pas se chevaucher (voir memmove pour une alternative plus sûre en cas de chevauchement).

Mais je suis confus par cette déclaration:

dans ce cas, la destination ne doit pas être considérée comme une valeur nulle chaîne terminée C (lecture en tant que telle déborderait)

Depuis si num > strlen(source), il remplira '\0' à la fin, '\0' est en fait un caractère nul (se terminant) dans une chaîne, pourquoi il ne doit pas être considéré comme une chaîne C terminée par un caractère nul?

J'ai écrit ci-dessous code pour vérifier:

char from[] = { 'h', 'e', 'l', 'l', 'o', '\0' }; 
    char to[1024]; 
    for (int i = 0; i < 1024; i++) { 
     to[i] = 'e'; 
    } 
    strncpy(to, from, 1024); 
    printf("from %s\n", from); 

Il fonctionne très bien avec la sortie ci-dessous:

from hello 
to hello 
+3

'strncpy': ne l'utilisez pas. – chqrlie

+0

L'absence d'un '' \ 0'' est où 'strlen (source)> num', donc je pense que vous avez juste un simple malentendu - essayez' strncpy (to, from, 2); 'à la place. –

Répondre

6

Il parle du cas où strlen(source)>num. Il ne copiera que num caractères, dont aucun n'est NUL et il n'ajoutera pas de NUL.

+1

... et pour vous assurer d'obtenir * un * terminateur NUL, utilisez 'strlcpy' au lieu de' strncpy'. – Danra

4

strncpy(dst, src, len) ajoute uniquement un terminateur null à dst s'il existe un terminateur null dans src dans les premiers len octets. Votre code peut sembler fonctionner, car il peut ou ne peut pas être un caractère null après le tableau to[]. Un meilleur test est:

char source[] = "source"; 
char dest[] = "destination"; 
strncpy(dest, source, 6); 
printf("%s\n", dest); 

Le résultat devrait être:

sourceation 

Si vous écrivez à la place strncpy(dest, source, 7), la sortie est juste le mot source.

2

La sémantique de strncpy(), même expliquée précisément comme ils sont dans la référence C++ ci-dessus, est largement méconnue. Le comportement de cette fonction est contre-intuitif et sujet aux erreurs.

Pour éviter les problèmes lors de son utilisation ou plus tard dans le processus de développement, lorsque le mainteneur interprète mal le code et ajoute des bogues plus subtils, il existe une solution simple: N'UTILISEZ JAMAIS CETTE FONCTION.

Vous pouvez lire plus de détails à ce sujet dans this article by Bruce Dawson. Pour répondre à votre question: si la chaîne source est plus longue que la taille passée en tant que troisième argument (correspondant généralement à la taille du tampon de destination), la fonction copie les caractères de taille vers la destination et aucun octet nul ne sera présent parmi ceux-ci. L'appel strlen(destination); appelle alors un comportement indéfini car il tentera de lire au-delà de la fin du tableau jusqu'à ce qu'il trouve un terminateur null. Ce comportement spécifique est ce qui rend strncpy donc sujettes aux erreurs.

+0

@EvilTeach: J'ai mis à jour la réponse. Il est important de dissuader les débutants d'utiliser cette fonction sujette aux erreurs. J'ai vu tant de cas d'utilisation abusive, même par des programmeurs expérimentés ... Il agit comme un attracteur universel de bogue. – chqrlie

+1

C'est la meilleure réponse maintenant. Il est dommage que l'utilisation de cette fonction ne puisse JAMAIS clignoter entre le rouge et le noir. – EvilTeach

+0

je voudrais ajouter strtok, atoi, atof et toute la famille scanf à la liste des fonctions à éviter. – EvilTeach