strdup() - ¿Qué hace en C?

Resuelto Manoj Doubts asked hace 16 años • 11 respuestas

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

Manoj Doubts avatar Oct 31 '08 14:10 Manoj Doubts
Aceptado

Exactamente lo que parece, suponiendo que esté acostumbrado a la forma abreviada en la que C y UNIX asignan palabras, duplica cadenas :-)

Teniendo en cuenta que en realidad no es parte del estándar ISO C actual (C17) (a) (es una cosa POSIX), efectivamente hace lo mismo que el siguiente código:

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 otras palabras:

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

  2. Si la asignación falla, se establece errnoy ENOMEMregresa NULLinmediatamente. La configuración de errnoto ENOMEMes algo mallocque se hace en POSIX, por lo que no es necesario hacerlo explícitamente en nuestro archivo strdup. Si no es compatible con POSIX, ISO C en realidad no exige la existencia de ENOMEM, por lo que no lo he incluido aquí (b) .

  3. De lo contrario, la asignación funcionó, por lo que copiamos la cadena anterior a la nueva cadena (c) 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 bibliotecas que valga su salario puede haber proporcionado un código muy optimizado dirigido al procesador particular que se utiliza.

Otra cosa a tener en cuenta es que parece que actualmente está programado para estar en la iteración C2x del estándar, junto con strndup, según el borrador N2912del documento.


(a) Sin embargo, las funciones que comienzan con struna letra minúscula están reservadas por la norma para instrucciones futuras. De C11 7.1.3 Reserved identifiers:

Cada encabezado declara o define todos los identificadores enumerados en su subcláusula asociada y, opcionalmente, declara o define identificadores enumerados en su subcláusula asociada de direcciones de biblioteca futuras. *

Las instrucciones futuras se string.hpueden encontrar en C11 7.31.13 String handling <string.h>:

Los nombres de funciones que comienzan con str, memo wcsy una letra minúscula se pueden agregar a las declaraciones en el <string.h>encabezado.

Así que probablemente deberías llamarlo de otra manera si quieres estar seguro.


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

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

(c) Tenga en cuenta que lo uso strcpypara eso ya que muestra claramente la intención. En algunas implementaciones, puede ser más rápido (dado que ya conoce la longitud) utilizar memcpy, ya que pueden permitir transferir los datos en fragmentos más grandes o en paralelo. O puede que no :-) Mantra de optimización n.º 1: "mide, no adivines".

En cualquier caso, si decide seguir ese camino, haría algo como:

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
}
paxdiablo avatar Oct 31 '2008 07:10 paxdiablo
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 sea un poco más rápido que con, ya que no es necesario volver a buscar strcpy()el carácter (ya lo era con ).\0strlen()

Patrick Schlüter avatar Nov 27 '2009 15:11 Patrick Schlüter

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

Chris Young avatar Oct 31 '2008 09:10 Chris Young

Del hombre strdup :

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

VonC avatar Oct 31 '2008 07:10 VonC

strdup() realiza una asignación de memoria dinámica para la matriz de caracteres, incluido el carácter final '\0' y devuelve la dirección de la memoria del montón:

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
}

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

Karshit avatar Jun 27 '2013 09:06 Karshit