2011-06-29 22 views
11
char *p = "string"; //creates pointer to constant string 

char p[] = "string"; //just an array with "string" 

Estoy un poco confundido acerca de por qué en el primer ejemplo crea un puntero a una cadena constante? ¿No debería ser solo un puntero que hace referencia a un lugar en la memoria con "cadena"?Puntero a cadena const en C

+0

Le recomendamos leer la sección 6 (y otras) de [la c-faq] (http://c-faq.com/). – pmg

+0

encontró algo interesante: http://www.geeksforgeeks.org/storage-for-strings-in-c/ – NDestiny

Respuesta

14

Desafortunadamente es legal en C (y en C++ 03, por compatibilidad). Pero cualquier intento de modificar el literal de cadena a través del puntero dará como resultado un comportamiento Indefinido. Entonces, es mejor asignar siempre la cadena literal a un const char*

const char * cp = "Hello"; //OK 
char* p = "Hello"; //OK (unfortunately) 
cp[0] = 'Y'; //Compile-time error, good 
p[0] = 'Y'; //no compiler error, undefined behavior 
21

En el primer caso, "string" se puede almacenar en un área de solo lectura del proceso, por lo que intentar modificar la memoria apuntada por p podría causar un comportamiento indefinido.

En el segundo caso, la memoria real se asigna e inicializa en la pila en tiempo de ejecución (o en una sección apropiada del proceso al inicio del programa si no es una variable local), por lo que la modificación es correcta.

El primer caso se puede ilustrar como esto:

+---+   +---+---+---+---+---+---+---+ 
| | ----> | s | t | r | i | n | g | \0| 
+---+   +---+---+---+---+---+---+---+ 
    p 

Considerando que el segundo caso es:

+---+---+---+---+---+---+---+ 
| s | t | r | i | n | g | \0| 
+---+---+---+---+---+---+---+ 
       p 

Las dos declaraciones tienen una diferencia significativa, aunque es posible que haya oído hablar de que son el mismo de los libros de programación de baja calidad C.

El primero es un puntero de tipo char *, mientras que el segundo es un array de tipo char []. Los identificadores de matriz se descomponen en un puntero en algunos contextos, pero eso no los convierte en punteros.

Un puntero es meramente una dirección y una matriz es "toda la cosa" - en el primer caso sizeof(p) produce el tamaño de un puntero (por lo general 4 o 8 dependiendo de la máquina de destino), y en el segundo caso se produce 7 * sizeof(char), la longitud de la cadena real.

+0

"un área de solo lectura del ejecutable": tal vez "proceso" es más significativo aquí ... "ejecutable "está más enfocado en el archivo de disco que contiene el programa, pero la clave es que la memoria en la que se copiará ese contenido de archivo se hará de solo lectura por la mayoría de los cargadores modernos del sistema operativo. Me gusta que haya puesto su segundo caso 'p' debajo de 'i' ... una parte de mí quiere tenerlo bajo 's' para enfatizar" arreglo que comienza en ... "- ya que es importante comprender las compensaciones de arreglo pero has enfatizado que p * es * toda la matriz que contiene los datos textuales, que es mucho más importante en este contexto. +1 –

+0

Muy buena respuesta. También el método gráfico para explicar las diferencias. –

+0

@Tony: gracias por las correcciones, actualicé mi respuesta. –

3

El primero crea un puntero y lo establece en la dirección de una cadena constante (presumiblemente en una región que no tiene protección de escritura en las páginas). Escribir en este puntero es ilegal (y probablemente se bloqueará).

El segundo crea una matriz y copia caracteres en ella. Escribir en esta matriz escribirá en algún lugar de tu pila y es perfectamente legal.

+0

En el primer caso, escribir en el puntero no es ilegal en C, es un comportamiento indefinido. Podría causar un error de protección de memoria o podría funcionar bien. Depende completamente de la combinación del sistema operativo del compilador y la arquitectura de la máquina. – JeremyP

1

En el primer caso, "cadena" pueden ser almacenados en un área de sólo lectura del proceso, por lo que intentar modificar la memoria apuntado por p haría causa un comportamiento indefinido

Se puede probar ejecutando la línea de códigos anterior repetidamente.

char *p="string"; 

notará que el contenido de p (es decir, la dirección de "cadena") permanece constante.

char p[] = "string"; 

para estas memorias se asignan cada vez que ejecuta el contenido de p cambios.

Cuestiones relacionadas