También hay strdupa () (en la biblioteca GNU C), una buena función que es similar a strdup (), pero asigna memoria en la pila. Su programa no necesita liberar la memoria explícitamente, ya que en el caso de strdup (), se liberará automáticamente cuando salga de la función donde se llamó strdupa ()
dmityugov
11
strdupaes peligroso y no debe usarse a menos que ya haya determinado que strlenes muy pequeño. Pero luego podría usar una matriz de tamaño fijo en la pila.
R .. GitHub DEJA DE AYUDAR AL HIELO
44
@slacker google translate no es útil ... ¿Qué significa strdup/ strdupasignifica en polaco?
Exactamente cómo suena, suponiendo que esté acostumbrado a la forma abreviada en que C y UNIX asignan palabras, duplica las cadenas :-)
Teniendo en cuenta que en realidad no es parte del estándar ISO C en sí (a) (es una cosa POSIX), efectivamente está haciendo lo mismo que el siguiente código:
char*strdup(constchar*src){char*dst = malloc(strlen (src)+1);// Space for length plus nulif(dst == NULL)return NULL;// No memory
strcpy(dst, src);// Copy the charactersreturn dst;// Return the new string}
En otras palabras:
Intenta asignar suficiente memoria para contener la cadena anterior (más un carácter '\ 0' para marcar el final de la cadena).
Si la asignación no, se establece errnopara ENOMEMy vuelve NULLinmediatamente. La configuración de errnoto ENOMEMes algo que mallochace en POSIX, por lo que no necesitamos hacerlo explícitamente en nuestro strdup. Si no cumple con POSIX, ISO C en realidad no exige la existencia de ENOMEMlo que no he incluido aquí (b) .
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 biblioteca que valga su salario puede haber proporcionado un código altamente optimizado dirigido al procesador particular que se está utilizando.
(a) Sin embargo, las funciones que comienzan con struna letra minúscula están reservadas por el estándar para futuras instrucciones. 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 los identificadores enumerados en su subcláusula de direcciones de biblioteca futura asociada. **
Las direcciones futuras para string.hse pueden 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.
Por lo tanto, probablemente debería llamarlo de otra manera si desea estar seguro.
(b) El cambio básicamente se reemplazaría if (d == NULL) return NULL;con:
if(d == NULL){
errno = ENOMEM;return NULL;}
(c) Tenga en cuenta que lo uso strcpypara eso, ya que eso muestra claramente la intención. En algunas implementaciones, puede ser más rápido (ya que ya conoce la longitud) de usar memcpy, ya que pueden permitir la transferencia de datos en fragmentos más grandes o en paralelo. O puede que no :-) Mantra de optimización # 1: "medir, no adivinar".
En cualquier caso, si decide ir por esa ruta, haría algo como:
char*strdup(constchar*src){size_t len = strlen(src)+1;// String plus '\0'char*dst = malloc(len);// Allocate spaceif(dst == NULL)return NULL;// No memory
memcpy (dst, src, len);// Copy the blockreturn dst;// Return the new string}
Vale la pena señalar que, como implica la implementación de muestra de Pax, strdup (NULL) no está definido y no es algo que se pueda esperar que se comporte de ninguna manera predecible.
Descanse
2
Además, creo que malloc () establecería errno, por lo que no debería tener que configurarlo usted mismo. Yo creo que.
Chris Lutz
55
@Alcot, strdupes para aquellas situaciones en las que desea asignar memoria de montón para la copia de cadena. De lo contrario, tienes que hacerlo tú mismo. Si ya tiene un búfer lo suficientemente grande (mal ubicado o no), sí, úselo strcpy.
paxdiablo
2
@acgtyrant: si, por estándar, te refieres al estándar ISO (el verdadero estándar C), no, no es parte de él. Que es parte del estándar POSIX. Sin embargo, hay muchas implementaciones de C que lo proporcionan, a pesar de no ser una parte oficial de ISO C. Sin embargo, incluso si no lo hicieran, el trazo de cinco en esta respuesta debería ser más que suficiente.
paxdiablo
2
Buen punto, @chux, ISO exige solo { EDOM, EILSEQ, ERANGE }como códigos de error requeridos. Han actualizado la respuesta para dar cuenta de esto.
paxdiablo
86
char* strdup(constchar* 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 strcpy()ya que \0no es necesario volver a buscar el carácter (ya estaba con strlen()).
Gracias. En mi implementación personal, lo hago aún "peor". return memcpy(malloc(len), s, len);como prefiero el bloqueo en la asignación en lugar de la NULLfalla en la asignación.
Patrick Schlüter
3
La desreferenciación de @tristopia NULLno tiene que bloquearse; Es indefinido. Si quieres asegurarte de que se bloquea, escribe una emallocllamada abortque falla.
Dave
Lo sé, pero mi implementación está garantizada para ejecutarse solo en Solaris o Linux (por la naturaleza misma de la aplicación).
Patrick Schlüter
@tristopia: Es bueno tener la costumbre de hacer las cosas de la mejor manera. Acostúmbrese a usarlo emallocincluso si no es necesario en Solaris o Linux, de modo que lo usará en el futuro cuando escriba código en otras plataformas.
ArtOfWarfare
51
No tiene sentido repetir las otras respuestas, pero tenga en cuenta que strdup()puede hacer lo que quiera desde una perspectiva C, ya que no forma parte de ningún estándar C. Sin embargo, está definido por POSIX.1-2001.
Es strdup()portátil? No, no está disponible en un entorno que no sea POSIX (implementable trivialmente 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 el de C e incluso más popular.
PP
2
@BlueMoon Creo que el punto es que una implementación de C que afirma que no cumple con POSIX aún puede proporcionar una strdupfunción como una extensión. En tal implementación, no hay garantía de que se strdupcomporte de la misma manera que la función POSIX. No conozco ninguna de esas implementaciones, pero una implementación legítima no maliciosa podría proporcionar char *strdup(char *)por razones históricas y rechazar los intentos de pasar a const char *.
¿Cuál es la diferencia entre C standard y POSIX? Por estándar C, ¿quiere decir que no existe en las bibliotecas estándar C?
Koray Tugay
@KorayTugay Son estándares diferentes. Es mejor tratarlos como no relacionados, a menos que sepa que el estándar para una función C particular se ajusta al estándar POSIX, y que su compilador / biblioteca se ajusta al estándar para esa función.
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.
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 de almacenamiento dinámico:
Entonces, lo que hace es darnos otra cadena idéntica a la cadena dada por su argumento, sin requerir que asignemos memoria. Pero aún necesitamos liberarlo, más tarde.
Realiza una copia duplicada de la cadena que se pasa ejecutando un malloc y strcpy de la cadena que se pasa. El búfer mallocado se devuelve a la persona que llama, de ahí la necesidad de ejecutar libremente el valor de retorno.
Lo más valioso que hace es darle otra cadena idéntica a la primera, sin requerir que usted asigne memoria (ubicación y tamaño). Pero, como se señaló, aún necesita liberarlo (pero que tampoco requiere un cálculo de cantidad).
Entonces, si desea que la cadena que ha copiado se use en otra función (como se crea en la sección de montón), puede usar strdup, de lo contrario strcpyes suficiente,
La función strdup () es una abreviatura de duplicado de cadena, toma un parámetro como una constante de cadena o un literal de cadena y asigna el espacio suficiente para la cadena y escribe los caracteres correspondientes en el espacio asignado y finalmente devuelve la dirección del asignado espacio para la rutina de llamadas.
strdupa
es peligroso y no debe usarse a menos que ya haya determinado questrlen
es muy pequeño. Pero luego podría usar una matriz de tamaño fijo en la pila.strdup
/strdupa
significa en polaco?Respuestas:
Exactamente cómo suena, suponiendo que esté acostumbrado a la forma abreviada en que C y UNIX asignan palabras, duplica las cadenas :-)
Teniendo en cuenta que en realidad no es parte del estándar ISO C en sí (a) (es una cosa POSIX), efectivamente está haciendo lo mismo que el siguiente código:
En otras palabras:
Intenta asignar suficiente memoria para contener la cadena anterior (más un carácter '\ 0' para marcar el final de la cadena).
Si la asignación no, se establece
errno
paraENOMEM
y vuelveNULL
inmediatamente. La configuración deerrno
toENOMEM
es algo quemalloc
hace en POSIX, por lo que no necesitamos hacerlo explícitamente en nuestrostrdup
. Si no cumple con POSIX, ISO C en realidad no exige la existencia deENOMEM
lo que no he incluido aquí (b) .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 biblioteca que valga su salario puede haber proporcionado un código altamente optimizado dirigido al procesador particular que se está utilizando.
(a) Sin embargo, las funciones que comienzan con
str
una letra minúscula están reservadas por el estándar para futuras instrucciones. DeC11 7.1.3 Reserved identifiers
:Las direcciones futuras para
string.h
se pueden encontrar enC11 7.31.13 String handling <string.h>
:Por lo tanto, probablemente debería llamarlo de otra manera si desea estar seguro.
(b) El cambio básicamente se reemplazaría
if (d == NULL) return NULL;
con:(c) Tenga en cuenta que lo uso
strcpy
para eso, ya que eso muestra claramente la intención. En algunas implementaciones, puede ser más rápido (ya que ya conoce la longitud) de usarmemcpy
, ya que pueden permitir la transferencia de datos en fragmentos más grandes o en paralelo. O puede que no :-) Mantra de optimización # 1: "medir, no adivinar".En cualquier caso, si decide ir por esa ruta, haría algo como:
fuente
strdup
es para aquellas situaciones en las que desea asignar memoria de montón para la copia de cadena. De lo contrario, tienes que hacerlo tú mismo. Si ya tiene un búfer lo suficientemente grande (mal ubicado o no), sí, úselostrcpy
.{ EDOM, EILSEQ, ERANGE }
como códigos de error requeridos. Han actualizado la respuesta para dar cuenta de esto.Tal vez el código sea un poco más rápido que con
strcpy()
ya que\0
no es necesario volver a buscar el carácter (ya estaba constrlen()
).fuente
return memcpy(malloc(len), s, len);
como prefiero el bloqueo en la asignación en lugar de laNULL
falla en la asignación.NULL
no tiene que bloquearse; Es indefinido. Si quieres asegurarte de que se bloquea, escribe unaemalloc
llamadaabort
que falla.emalloc
incluso si no es necesario en Solaris o Linux, de modo que lo usará en el futuro cuando escriba código en otras plataformas.No tiene sentido repetir las otras respuestas, pero tenga en cuenta que
strdup()
puede hacer lo que quiera desde una perspectiva C, ya que no forma parte de ningún estándar C. Sin embargo, está definido por POSIX.1-2001.fuente
strdup()
portátil? No, no está disponible en un entorno que no sea POSIX (implementable trivialmente 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 el de C e incluso más popular.strdup
función como una extensión. En tal implementación, no hay garantía de que sestrdup
comporte de la misma manera que la función POSIX. No conozco ninguna de esas implementaciones, pero una implementación legítima no maliciosa podría proporcionarchar *strdup(char *)
por razones históricas y rechazar los intentos de pasar aconst char *
.De strdup man :
La
strdup()
función devolverá un puntero a una nueva cadena, que es un duplicado de la cadena a la que apuntas1
. El puntero devuelto se puede pasar afree()
. Se devuelve un puntero nulo si no se puede crear la nueva cadena.fuente
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 de almacenamiento dinámico:
Entonces, lo que hace es darnos otra cadena idéntica a la cadena dada por su argumento, sin requerir que asignemos memoria. Pero aún necesitamos liberarlo, más tarde.
fuente
Realiza una copia duplicada de la cadena que se pasa ejecutando un malloc y strcpy de la cadena que se pasa. El búfer mallocado se devuelve a la persona que llama, de ahí la necesidad de ejecutar libremente el valor de retorno.
fuente
strdup
ystrndup
se definen en sistemas compatibles con POSIX como:La función strdup () asigna suficiente memoria para una copia de la cadena
str
, hace la copia y le devuelve un puntero.El puntero puede usarse posteriormente como argumento para la función
free
.Si no hay suficiente memoria disponible,
NULL
se devuelve yerrno
se establece enENOMEM
.La función strndup () copia en la mayoría de los
len
caracteres de la cadenastr
siempre nulo terminando la cadena copiada.fuente
Lo más valioso que hace es darle otra cadena idéntica a la primera, sin requerir que usted asigne memoria (ubicación y tamaño). Pero, como se señaló, aún necesita liberarlo (pero que tampoco requiere un cálculo de cantidad).
fuente
La declaración:
es equivalente a (aparte del hecho de que esto cambia los punteros):
Mientras:
es equivalente a:
Entonces, si desea que la cadena que ha copiado se use en otra función (como se crea en la sección de montón), puede usar
strdup
, de lo contrariostrcpy
es suficiente,fuente
La función strdup () es una abreviatura de duplicado de cadena, toma un parámetro como una constante de cadena o un literal de cadena y asigna el espacio suficiente para la cadena y escribe los caracteres correspondientes en el espacio asignado y finalmente devuelve la dirección del asignado espacio para la rutina de llamadas.
fuente
strdup
no necesita ser una cadena constante, debe ser una cadena C, es decir, una matriz terminada en nulochar
.