¿Cuál es la diferencia entre strcpy y stpcpy?

5 minutos de lectura

Mientras lee la página del manual para strcpydescubrí 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í?

  • @{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

avatar de usuario
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 de strcat 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


avatar de usuario
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;).

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).

¿Ha sido útil esta solución?