web-dev-qa-db-fra.com

strdup () - que fait-il en C?

Quel est le but de la fonction strdup() en C?

293
Manoj Doubts

Exactement ce que cela ressemble, en supposant que vous soyez habitué à la manière abrégée selon laquelle C et UNIX assignent des mots, il duplique des chaînes de caractères = :-)

Garder à l'esprit que cela ne fait en réalité pas partie de la norme ISO C(une) (c'est un truc POSIX), il fait exactement la même chose que le code suivant:

char *strdup(const char *src) {
    char *dst = malloc(strlen (src) + 1);  // Space for length plus nul
    if (dst == NULL) return NULL;          // No memory
    strcpy(dst, src);                      // Copy the characters
    return dst;                            // Return the new string
}

En d'autres termes:

  1. Il essaie d'allouer suffisamment de mémoire pour contenir l'ancienne chaîne (plus un caractère '\ 0' pour marquer la fin de la chaîne).

  2. Si l'attribution échoue, il place errno sur ENOMEM et renvoie NULL immédiatement. Régler errno sur ENOMEM est quelque chose que malloc fait dans POSIX; nous n'avons donc pas besoin de le faire explicitement dans notre strdup. Si vous êtes non conforme à POSIX, ISO C n'impose pas l'existence de ENOMEM alors je ne l'ai pas incluse ici.(b).

  3. Sinon, l'allocation a fonctionné et nous avons donc copié l'ancienne chaîne dans la nouvelle chaîne.(c) et renvoyer la nouvelle adresse (que l'appelant est responsable de libérer à un moment donné).

Gardez à l'esprit que c'est la définition conceptuelle. Tout rédacteur de bibliothèque digne de ce salaire peut avoir fourni un code fortement optimisé ciblant le processeur utilisé.


(une) Cependant, les fonctions commençant par str et une lettre minuscule sont réservées par la norme pour les directions futures. De C11 7.1.3 Reserved identifiers:

Chaque en-tête déclare ou définit tous les identifiants répertoriés dans sa sous-clause associée et * éventuellement déclare ou définit les identifiants répertoriés dans sa sous-clause associée d'instructions de bibliothèque futures. **

Les futures directions pour string.h peuvent être trouvées dans C11 7.31.13 String handling <string.h>:

Les noms de fonction commençant par str, mem ou wcs et une lettre minuscule peuvent être ajoutés aux déclarations dans l'en-tête <string.h>.

Vous devriez donc probablement appeler cela autre chose si vous voulez être en sécurité.


(b) Le changement remplacerait fondamentalement if (d == NULL) return NULL; par:

if (d == NULL) {
    errno = ENOMEM;
    return NULL;
}

(c) Notez que j'utilise strcpy pour cela car cela montre clairement l'intention. Dans certaines implémentations, il peut être plus rapide (puisque vous connaissez déjà la longueur) d’utiliser memcpy, car elles peuvent permettre de transférer les données par lots plus importants ou en parallèle. Ou peut-être pas :-) Mantra d'optimisation n ° 1: "mesure, ne devine pas".

Dans tous les cas, si vous décidiez de suivre cette voie, vous feriez quelque chose comme:

char *strdup(const char *src) {
    size_t len = strlen(src) + 1;       // String plus '\0'
    char *dst = malloc(len);            // Allocate space
    if (dst == NULL) return NULL;       // No memory
    memcpy (dst, src, len);             // Copy the block
    return dst;                         // Return the new string
}
354
paxdiablo
char * strdup(const char * s)
{
  size_t len = 1+strlen(s);
  char *p = malloc(len);

  return p ? memcpy(p, s, len) : NULL;
}

Peut-être que le code est un peu plus rapide qu'avec strcpy() car le caractère \0 n'a pas besoin d'être recherché à nouveau (il l'était déjà avec strlen()).

85
Patrick Schlüter

Inutile de répéter les autres réponses, mais veuillez noter que strdup() peut faire tout ce qu'il veut du point de vue du C, car il ne fait partie d'aucun standard C. Il est cependant défini par POSIX.1-2001.

51
Chris Young

De strdup man :

La fonction strdup() doit renvoyer un pointeur sur une nouvelle chaîne, qui est un duplicata de la chaîne pointée par s1. Le pointeur renvoyé peut être passé à free(). Un pointeur null est renvoyé si la nouvelle chaîne ne peut pas être créée.

17
VonC

strdup () effectue une allocation de mémoire dynamique pour le tableau de caractères, y compris le caractère de fin '\ 0', et renvoie l'adresse de la mémoire de tas:

char *strdup (const char *s)
{
    char *p = malloc (strlen (s) + 1);   // allocate memory
    if (p != NULL)
        strcpy (p,s);                    // copy string
    return p;                            // return the memory
}

Donc, ce qu'il fait est de nous donner une autre chaîne identique à la chaîne donnée par son argument, sans nous obliger à allouer de la mémoire. Mais nous devons encore le libérer, plus tard.

4
Karshit

strdup et strndup sont définis dans les systèmes compatibles POSIX comme suit:

char *strdup(const char *str);
char *strndup(const char *str, size_t len);

La fonction strdup () alloue suffisamment de mémoire pour une copie de la chaîne str, effectue la copie et renvoie un pointeur sur celle-ci.

Le pointeur peut ensuite être utilisé comme argument de la fonction free.

Si la mémoire disponible est insuffisante, NULL est renvoyé et errno est défini sur ENOMEM.

La fonction strndup () copie au plus _ len caractères de la chaîne str toujours null terminant la chaîne copiée.

3
Sujay Kumar

Il crée une copie de la chaîne transmise en exécutant un malloc et strcpy de la chaîne transmise. Le tampon malloc est renvoyé à l'appelant, d'où la nécessité exécuter gratuit sur la valeur de retour.

3
jussij

La chose la plus précieuse est de vous donner une autre chaîne identique à la première, sans vous obliger à allouer de la mémoire (emplacement et taille) vous-même. Mais, comme indiqué, vous devez toujours le libérer (mais cela ne nécessite pas non plus de calcul de quantité.)

1
dkretz

La déclaration:

strcpy(ptr2, ptr1);

est équivalent à (autre que le fait que cela change les pointeurs):

while(*ptr2++ = *ptr1++);

Tandis que:

ptr2 = strdup(ptr1);

est équivalent à:

ptr2 = malloc(strlen(ptr1) + 1);
if (ptr2 != NULL) strcpy(ptr2, ptr1);

Donc, si vous voulez que la chaîne que vous avez copiée soit utilisée dans une autre fonction (comme elle est créée dans la section heap), vous pouvez utiliser strdup, sinon strcpy suffit,

1

La fonction strdup () est un raccourci pour la duplication de chaîne. Elle prend un paramètre sous la forme d’une constante de chaîne ou d’un littéral de chaîne. Elle alloue juste assez d’espace pour la chaîne. espace à la routine d'appel.

0
AnkitSablok