2011-08-01 19 views
20

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

int main(void) { 

char s[4]; 

s = "abc"; //Fails 
strcpy(s, "abc"); //Succeeds 

return 0; 
} 

¿Cuál es la razón por la que 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.

Respuesta

12

Eso es simplemente lo que las matrices están en C. No puede asignarlas. Puede utilizar punteros si le gusta:

char *p; 
p = "abc"; 

Por cierto, hay una C FAQ.

Las matrices son `` ciudadanos de segunda clase '' en C; un resultado de este perjuicio es que no puede asignarles.

+0

Sí, sí uso punteros, simplemente no entiendo por qué s = "abc" no funciona en mi ejemplo. s es una matriz de caracteres, y también lo es "abc" ... –

+4

@ C_p678 - no, 's' es una matriz de caracteres," abc "es un puntero a cadena constante. – MByD

+3

@MByD: no del todo correcto. '" abc "' no es un puntero. '" abc "' una matriz de tipo 'char [4]', que en este contexto se descompone en un puntero de tipo 'char *'. Tenga en cuenta que en C la cadena no es constante. No es modificable, pero el tipo en sí no incluye el calificador 'const'. – AnT

24

Las matrices en C no se pueden asignar ni se pueden inicializar. 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 char.

El lenguaje C hereda este comportamiento de arrays 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. usted puede 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.

+1

Solo para aclarar, todos los tipos de matriz se pueden inicializar con un inicializador adecuado de la forma '{val0, val1, ...}'. –

+0

No * tiene * para usar una función de biblioteca; puedes asignar personajes individuales, p. 'for (char * dst = s, * src =" abc "; * dst ++ = * srC++;);'. Sin embargo, la función de biblioteca es una mejor opción, ya que es más fácil de leer y puede optimizarse para el sistema. –

+1

Sí, para tocar más sobre lo que @AnT dijo, 'strcpy()' es casi exactamente como 'memcpy()', excepto que incluye el byte nulo. – RastaJedi

1

Respuesta breve: razones históricas. C nunca tuvo un tipo de cuerda integrado. No fue hasta que surgió 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 puede copiar los datos apuntados por el puntero (en este caso, ese 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 es posible usar memcpy copiar la cadena en s pero que requiere que se pasa en la longitud de los datos a copiar, y para asegurar la terminación de 0 (NULL) está presente en s

+3

El tipo de '" abc "' es 'char [4]'. –

+3

Y 'strcpy' no es una inicialización sino una asignación. Las matrices de caracteres se pueden inicializar como todas las demás matrices, ver la respuesta de AndreyT. –

0

El lenguaje C carece de sintaxis 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.

cadenas Cero terminados son inferiores a otras formas para casi todos los fines otra de literales de cadena, pero literales están tan lejos la forma más común de cadena que muchos programas tendrán que tratar, y por lo tanto no es considerable ventaja al tener las funciones de la biblioteca lidiar 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.

Cuestiones relacionadas