Mientras lee la página del manual para strcpy
descubrí la función stpcpy
también existe Sin embargo, la única diferencia que pude notar en la página del manual es:
char *
stpcpy(char *s1, const char *s2);
char *
strcpy(char *restrict s1, const char *restrict s2);
Entonces, ¿qué hace restrict
significa aquí?
Hormiga
La pregunta que está haciendo en el título y la pregunta sobre restrict
son en realidad dos preguntas diferentes totalmente sin relación. Las otras respuestas ya le han proporcionado algunos buenos enlaces que lo ayudarán a aprender más sobre restrict
.
Sin embargo, la principal diferencia entre estas dos funciones no es realmente la restrict
especificador De hecho, en la versión C99 de la especificación del lenguaje C, strcpy
también tiene restrict
calificación sobre sus parámetros. Lo que ve en su página man para strcpy
simplemente no está actualizado para cumplir con C99.
La principal diferencia (que parece haber pasado por alto) es el valor de retorno de stpcpy
. stpcpy
devuelve el puntero a la terminación \0
carácter de la cadena de destino. Esto aclara inmediatamente el propósito de stpcpy
y la razón detrás de su existencia: esta función está destinada a ser utilizada como un reemplazo inteligente para strcat
funcione en situaciones en las que necesite concatenar varias subcadenas en una cadena. Verás, strcat
funciona bastante mal en tal aplicación (incluso diría que strcat
no tiene usos significativos en código real). el problema con strcat
es que vuelve a escanear la cadena de destino cada vez que le agregas algo, por lo que hace mucho trabajo innecesario y básicamente genera más calor que luz. Por ejemplo, el siguiente código sufre de ese problema
const char *part1, *part2, *part3, *part4;
...
char buffer[size]; /* assume that `size` is calculated properly */
strcpy(buffer, part1);
strcat(buffer, part2);
strcat(buffer, part3);
strcat(buffer, part4);
Este código se puede volver a implementar de una manera mucho más razonable usando stpcpy
stpcpy(stpcpy(stpcpy(stpcpy(buffer, part1), part2), part3), part4);
Y si no le gustan las llamadas encadenadas, puede usar un puntero intermedio para almacenar el valor de retorno de intermedio stpcpy
llamadas
char *end = buffer;
end = stpcpy(end, part1);
end = stpcpy(end, part2);
end = stpcpy(end, part3);
end = stpcpy(end, part4);
Por supuesto, vale la pena mencionar que strcpy
y strcat
son funciones estándar, mientras que stpcpy
no es.
-
Es una pena que no pueda dar la nota correcta a dos respuestas. Así que termino simplemente votando el tuyo y agradeciéndote por proporcionar estos excelentes ejemplos.
– sidilio
29 de abril de 2011 a las 1:56
-
Creo que esta es la respuesta real a la pregunta, al menos la pregunta en el título.
– Seanoseanohay
5 de agosto de 2015 a las 4:07
-
Vale la pena agregar que stpcpy está definido en POSIX desde la versión 2008.
– Lobo gris
21/09/2021 a las 21:46
-
“Incluso diría que
strcat
no tiene usos significativos en el código real”. El diseño excepcionalmente terrible destrcat
es lo que lo convierte en el ejemplo canónico en la publicación del blog Joel on Software que introdujo el término “algoritmo de Shlemiel el pintor” en el mundo de la programación.– ShadowRanger
24 de junio a las 13:40
james mcnellis
los restrict
le dice al compilador que s1
y s2
apunte a matrices diferentes y que no haya superposición en las matrices a las que apunta. En algunos casos, esto puede permitir que el compilador realice optimizaciones adicionales (es decir, posiblemente podría copiar bloques de varios caracteres sin tener que verificar la superposición).
Tenga en cuenta también que el valor de retorno es diferente: stpcpy
devuelve un puntero a la \0
que se copió en el búfer de destino mientras strcpy
devuelve un puntero al principio de la cadena (efectivamente hace un return s1;
).
-
stpcpy
es parte de POSIX: pubs.opengroup.org/onlinepubs/9699919799/functions/stpcpy.html– R.. GitHub DEJA DE AYUDAR A ICE
29 de abril de 2011 a las 2:01
-
Para ser justos, se acaba de agregar en POSIX 2008.
– R.. GitHub DEJA DE AYUDAR A ICE
29 de abril de 2011 a las 2:13
Entrada de Wikipedia para restrict
En breve, restrict
le dice al compilador que los segmentos de memoria señalados por s1 y s2 no se superponen; esto permite que el código realice menos comprobaciones de errores.
-
Muchas gracias por el enlace Mark, es impresionante que no conocía esa palabra clave.
– sidilio
29 de abril de 2011 a las 1:51
La otra diferencia es el valor de retorno. De la página del manual: “Las funciones strcpy() y strncpy() devuelven s1. La función stpcpy() devuelve un puntero al carácter final `\0′ de s1”.
-
Gracias por la completa respuesta Matt. me estaba confundiendo un poco con
stpcpy
no ser parte de C (o POSIX), ya que la página de manual que vi no mostraba ningún requisito además de incluir string.h . Pero tu consejo sobre los BSD lo dejó claro. Estoy en una variante de FreeBSD conocida popularmente como Mac OS X 😛– sidilio
29 de abril de 2011 a las 1:54
-
@sidyll: Bueno, podrías hacerlo mucho peor que Mac OS X, así que bravo 🙂
– Matt Carpintero
29 de abril de 2011 a las 4:13
strcpy devuelve s1 pero stpcpy devuelve s1+strlen(s2).
@{Todos}: Como siempre, recibí un montón de excelentes respuestas y no puedo marcarlas todas como correctas. Decidir cuál se marcará es la parte más difícil de estas preguntas. Trato de considerar lo que se cubrió en la pregunta y en algunos casos su edad; sin embargo, muchas respuestas diferentes brindan información importante sobre diferentes temas en diferentes niveles. Gracias a todos, y lo siento, pero no puedo hacer mucho más que votar a favor.
– sidilio
29 de abril de 2011 a las 2:01