2011-07-23 12 views
55

¿Puede alguien explicar por qué esto funciona con el puntero:¿Por qué se puede asignar una cadena a un puntero char *, pero no a una matriz char []?

char * str1; 

str1 = "Hello1"; 

str1 = "new string"; 

// but not this 
char str2 [] = "hello"; 
str2 = "four"; 

// or this 
char str3 []; 
str3 = "hello"; 
str3 = "hello"; 
+1

[Esta pregunta] (http://stackoverflow.com/questions/164194) cubre el mismo terreno, simplemente redactado de manera diferente. No estoy seguro si esto se duplica lo suficiente para cerrar, pero las respuestas se aplican. –

+4

@Tim Post: La supuesta pregunta duplicada y su respuesta son IMO no relacionadas con esta pregunta porque esta pregunta cosas de tiempo de compilación, la otra pregunta cosas de tiempo de ejecución –

Respuesta

71

Por qué funciona con punteros:
Cuando dice char * str1 en C, se están asignando un puntero en la memoria. Cuando se escribe str1 = "Hello";, que está creando una cadena literal en la memoria y hacer que el punto de puntero a ella. Cuando se crea otra cadena literal "new string" y la asigna a str1, todo lo que está haciendo es cambiante, donde el puntero.

Por qué no funciona con matrices:
Cuando dice char str2 [] = "Hello", que está creando una cadena literal y ponerlo en la matriz durante su definición. Está bien para no dar un tamaño, como la matriz calcula y añade un '\0' a ella. No puede reasignar nada a esa matriz sin cambiar el tamaño. Es por eso que str2 = "four" no funcionará.

En caso de str3, es el mismo caso. No ha definido el tamaño de la matriz en la definición, por lo que calculó su tamaño en 0. No puede asignar nada nuevo sin cambiar el tamaño de la matriz.

+0

Cheers, TryUrBest. La mayoría de los libros de C que he visto hacen un gran negocio con cuerdas, punteros y matrices. En el caso de str1 (el puntero), ¿es esa la manera de hacerlo? Deja de preocuparte por "¿Lo estoy haciendo al 100% de las respuestas correctas" y simplemente haz punteros a las cuerdas y úsalos como hice anteriormente? Usted dijo que el primer método mueve el puntero, es el orig. datos destruidos entonces, ¿o es una fuga? – nick

+0

olvidé el @. gracias – nick

+0

@tryurbest: ¿puedo agregar más preguntas? en caso de que se use char * str = "alguna cadena", esta cadena se considera cadena de tamaño fijo. Si más tarde, este puntero se procesa para agregar más cadenas. ¿Eso generará una violación de acceso a la memoria? ¡Gracias! en realidad, lo he probado y veo el error. Pero no estoy seguro de la parte "cadena de tamaño fijo" o "cadena constante" aquí –

19

una matriz y un puntero son cosas diferentes, es por eso. Puede asignar a un puntero, pero no puede asignarlo a una matriz. Se hace una excepción especial para la inicialización de matrices de caracteres con literales de cadena.

char a[] = "Hello"; //initialize a char array with string literal. Special case, OK 
char* p = "Hello"; //initializa a pointer with an array(which gets converted to pointer) 
p = "My"; //assign pointer to point to another value. OK 
a = "My"; //error, arrays cannot be assigned to. Use `strcpy` 

literales de cadena (tales como "Hola") tienen el tipo char[N]N donde es el número de caracteres (incluyendo la terminación de '\0'). Una matriz se puede convertir en un puntero a su primer elemento, pero las matrices y punteros no son lo mismo, independientemente de lo que digan algunos libros malos o maestros.

+2

No se olvide 'const' como un problema aquí. – Puppy

+4

@DeadMG: AFAIK en C literales de cadena no son 'const char [N]'. Son 'char [N]'. Es por eso que (solíamos) tener la conversión implícita a 'char *' de literales de cadena en C++. ¿Me equivoco? –

+0

@Armen: No, oficialmente no son 'const char [N]', pero en realidad, muy a menudo lo son. La mayoría de los compiladores colocan literales de cadena en la memoria de solo lectura. Eso significa que el usuario generalmente no debe intentar hacer '* p = 'A';'. –

5

En pocas palabras, debido a una matriz no es un objeto de primera clase en C/C++. La única forma de asignar una matriz es usar str (n) cpy o memcpy.

Mientras que una serie colapsa en un puntero cuando se pasa a una función, no es posible asignar a una matriz, excepto en tiempo de compilación como la inicialización.

3

Es simplemente porque, al escribir este código:

char str2 [] = "hello"; 

o incluso:

int arr[] = {1,2,4,4,5}; 

crea str2 o arr como un puntero constante. Es por eso que no puede reasignar ningún otro valor a estos punteros, mientras que en el caso posterior está creando un puntero normal y puede asignarle cualquier valor.

2

El caso de los punteros Funciona porque cuando se está asignando como str1="Hello", en realidad está creando una cadena literal llamado hola asignación en algún lugar de la memoria, y la asignación de la dirección del primer carácter del literal al puntero , y como el puntero no es constante, puede asignarlo nuevamente con diferentes direcciones. Y un punto más importante a tener en cuenta es que el literal de cadena creado está en la memoria de solo lectura.

El caso de la matriz de caracteres Puede asignar una cadena literal, mientras que la inicialización que se apoya en el lenguaje. Y no confundas la tarea con la inicialización. Durante la asignación, dado que es una matriz de caracteres, debe cambiar el carácter de carácter por carácter. Está intentando direccionar la primera dirección del literal de cadena al primer carácter de la matriz (el nombre de la matriz devuelve la dirección del primer elemento de la matriz). array). Y esto claramente no es correcto ya que el primer elemento no es puntero, no puede almacenar la dirección.

Cuestiones relacionadas