C – ¿Por qué es strcpy () necesario

¿Puede alguien explicarme por qué strcpy () es necesario para asignar cadenas a matrices de caracteres, como en el siguiente fragmento de código?

int main(void) { char s[4]; s = "abc"; //Fails strcpy(s, "abc"); //Succeeds return 0; } 

¿Cuál es la razón por la cual s = "abc" falla? ¿Y por qué strcpy () es la única forma de asignar cadenas a las matrices de caracteres después de que hayan sido declaradas? Me parece extraño que tengas que usar una función para llevar a cabo una tarea básica.

Las matrices en C son no asignables y no pueden copiarse. Así es como las matrices están en C. Históricamente, en el contexto de valor (en el RHS de asignación) las matrices decaen en punteros, que es lo que formalmente impide la asignación y la inicialización de la copia. Esto se aplica a todas las matrices, no solo a las matrices de caracteres.

El lenguaje C hereda este comportamiento de matrices de sus predecesores, los idiomas B y BCPL. En esos idiomas, las matrices estaban representadas por punteros físicos. (Y obviamente la reasignación de punteros no es lo que le gustaría que ocurriera cuando asigna una matriz a otra). En el lenguaje C, las matrices no son punteros, pero sí “simulan” el comportamiento histórico de las matrices B y BCPL al descomponerse a punteros en la mayoría de los casos. Este legado histórico es lo que mantiene las matrices en C no copiables hasta el día de hoy.

Una excepción de lo anterior es la inicialización con un literal de cadena. Es decir, puedes hacer

 char c[] = "abc"; 

Pero eso es todo.

Esto significa que siempre que quiera copiar una matriz, debe usar una función de copia de memoria a nivel de biblioteca, como memcpy . strcpy es solo un sabor de eso específicamente diseñado para trabajar con cadenas.

Eso es simplemente lo que las matrices están en C. No puedes asignarlas. Puede usar punteros si lo desea:

 char *p; p = "abc"; 

Por cierto, hay una C preguntas frecuentes .

Las matrices son “ ciudadanos de segunda clase ” en C; un resultado de este prejuicio es que no se puede asignar a ellos .

Respuesta corta: razones históricas. C nunca tuvo un tipo de cuerda integrado. No fue hasta que apareció C ++ que std :: string apareció, e incluso eso no llegó con las primeras implementaciones

Respuesta larga: el tipo de “abc” no es char[] , sino más bien char * . strcpy es un mecanismo con el que puedes copiar los datos apuntados por el puntero (en este caso, eso es ABC).

strcpy no es la única forma de inicializar una matriz, sin embargo, es lo suficientemente inteligente como para detectar y respetar la terminación 0 al final de la cadena. También puede usar memcpy para copiar la cadena en s pero eso requiere que pase la longitud de los datos que se van a copiar, y para asegurarse de que la terminación 0 (NULL) está presente en s

El lenguaje C carece de cualquier syntax conveniente para obtener un puntero a un literal de cadena junto con una indicación de su longitud. Algunos idiomas, incluidos muchos dialectos de Pascal, prefijan cada cadena con un byte que informa su longitud; esto funciona muy bien para muchos propósitos, pero limita los literales de cadena a 255 caracteres. El enfoque de C permite acomodar literales de cadena de cualquier longitud, pero agrega solo un byte de sobrecarga, independientemente de la longitud.

Las cadenas terminadas en cero son inferiores a otras formas para casi cualquier propósito que no sean cadenas literales, pero literalmente son la forma más común de cadena con la que muchos progtwigs tendrán que lidiar, y por lo tanto hay una ventaja considerable al tener funciones de biblioteca tratar con ellos de manera efectiva; luego es más fácil usar cadenas terminadas en cero en casos en que son menos ideales que tener un conjunto separado de rutinas de biblioteca para otros tipos.