2008-10-31 49 views
239

¿Cuál es el propósito de la función strdup() en C?strdup() - ¿qué hace en C?

+39

También hay strdupa() (en la biblioteca GNU C), una función agradable que es similar a strdup(), pero asigna memoria en la pila. Su programa no necesita liberar la memoria explícitamente como en el caso de strdup(), se liberará automáticamente cuando salga de la función donde strdupa() se llamó – dmityugov

+29

@dmityugov: +1 para 'strdupa()'. Esa función es especialmente entretenida de usar si hablas polaco :). – slacker

+0

¡Eso es gracioso! – Allbite

Respuesta

311

Exactamente de lo que parece (suponiendo que esté acostumbrado a la forma abreviada en que C y UNIX lo asigna) palabras), es duplica las cadenas.

Teniendo en cuenta que no es en realidad parte de la norma ISO C en sí (que es algo POSIX), que está haciendo efectivamente el mismo que el siguiente código:

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

En otras palabras:

  1. Trata de asignar suficiente memoria para contener la cadena anterior (más un carácter '\ 0' para marcar el final de la cadena).

  2. Si la asignación falló, establece errno en ENOMEM y devuelve NULL inmediatamente. El ajuste de errno a ENOMEM es algo que malloc hace en POSIX, así que no es necesario que lo haga explícitamente en nuestro strdup. Si tiene no Cumple con POSIX, ISO C en realidad no exige la existencia de ENOMEM, por lo que no he incluido esto aquí (a).

  3. De lo contrario, la asignación funcionó, por lo que copiamos la cadena anterior a la nueva cadena y devolvemos la nueva dirección (que la persona que llama es responsable de liberar en algún momento).

Tenga en cuenta que esa es la definición conceptual. Cualquier escritor de la biblioteca que valga su salario puede haber proporcionado un código altamente optimizado dirigido al procesador en particular que se utiliza.


(a) El cambio sería básicamente reemplazando if (d == NULL) return NULL; con:

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

Vale la pena señalar que, como la implementación de muestra de Pax Implica que strdup (NULL) no está definido y no es algo que pueda esperar comportarse de ninguna manera predecible. – unwind

+1

Además, creo que malloc() establecería errno, por lo que no debería tener que configurarlo usted mismo. Creo. –

+0

Ese es un buen punto, @Chris. Lo cambié porque tenía que mirar la página de manual de strdup() y me di cuenta de que lo había dejado. Pero olvidé que malloc() hizo eso por eso. Entonces revertiré el código. – paxdiablo

16

De strdup man:

La función strdup() devolverá un puntero a una nueva cadena, que es un duplicado de la cadena apuntada por s1. El puntero devuelto se puede pasar al free(). Se devuelve un puntero nulo si no se puede crear la nueva cadena.

3

Se hace una copia duplicada de la cadena pasada mediante la ejecución de un malloc y strcpy de la cadena pasada. La memoria intermedia malloc'ed se devuelve a la persona que llama, de ahí la necesidad de ejecutar libre en el valor de retorno.

1

Lo más valioso que hace es darle otra cadena idéntica a la primera, sin necesidad de que usted mismo asigne la memoria (ubicación y tamaño). Pero, como se señaló, aún necesita liberarlo (pero no requiere un cálculo de cantidad).

51

No tiene sentido repetir las otras respuestas, pero por favor tenga en cuenta que strdup() puede hacer lo que quiera desde una perspectiva de C, ya que no es parte de ningún estándar C Sin embargo, está definido por POSIX.1-2001.

+2

¿'strdup()' es portátil? No, no está disponible en un entorno que no sea POSIX (trivialmente aplicable de todos modos). Pero decir que una función POSIX puede hacer cualquier cosa es bastante pedante. POSIX es otro * estándar * que es tan bueno como C y aún más popular. –

+1

@BlueMoon Creo que el punto es que una implementación de C que afirma no cumplir con POSIX aún puede proporcionar una función 'strdup' como extensión. En tal implementación, no hay garantía de que 'strdup' se comporte de la misma manera que la función POSIX. No conozco ninguna de esas implementaciones, pero una implementación no maliciosa legítima podría proporcionar 'char * strdup (char *)' por razones históricas, y rechazar los intentos de pasar un 'const char *'. – hvd

+0

¿Cuál es la diferencia entre C estándar y POSIX? Por estándar de C, ¿no existe en las bibliotecas estándar de C? –

76
char * strdup(const char * s) 
{ 
    size_t len = 1+strlen(s); 
    char *p = malloc(len); 

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

Tal vez el código es un poco más rápido que con strcpy() como el carbón \0 no tiene que ser buscado de nuevo (Ya estaba con strlen()).

+9

+1 para una mejor implementación que la respuesta aceptada, y para usar correctamente el valor de retorno de 'memcpy'. –

+0

Gracias. En mi implementación personal lo hago incluso "peor". 'return memcpy (malloc (len), s, len);' como prefiero el bloqueo en la asignación en lugar del 'NULL' en la falla de asignación. –

+2

@tristopia dereferencing 'NULL' no tiene que bloquearse; es indefinido Si quiere asegurarse de que se bloquea, escriba un 'emalloc' que invoca' abort' al fallar. – Dave

2

strdup() hace la asignación de memoria dinámica para el arreglo de caracteres que incluye el carácter de fin '\ 0' y devuelve la dirección de la memoria de pila:

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 
} 

Por lo tanto, lo que hace es darnos otra cadena idéntica a la cadena dada por su argumento, sin requerir que nosotros asignemos memoria. Pero aún tenemos que liberarlo, más tarde.

1

La función strdup() es una abreviatura de cadena duplicada, toma un parámetro como una constante de cadena o una cadena literal y asigna suficiente espacio para la cadena y escribe los caracteres correspondientes en el espacio asignado y finalmente devuelve el dirección del espacio asignado a la rutina de llamada.

1

El strdup() función asigna memoria suficiente para obtener una copia de la cadena str , hace la copia, y devuelve un puntero a ella.

El puntero puede utilizarse posteriormente como argumento para la función libre (3).

Si no hay suficiente memoria disponible, se devuelve NULL y errno se establece en ENOMEM.

Los strndup() función copia en la mayoría de los len caracteres de la cadena str siempre nulo de terminación de la cadena copiada.

1

Es simple strcpy(ptr2, ptr1) es equivalente a while(*ptr2++ = *ptr1++)

donde como: strdup es equivalente a

ptr2 = malloc(strlen(ptr1)+1);

strcpy(ptr2,ptr1);

Así que si quieres la cadena de la que haya copiado a ser utilizado en otra función (como se crea en la sección de montón) puede usar strdup, sino strcpy es enou gh