2011-09-25 7 views
8

Estoy tratando de entender por qué el código siguiente es ilegal:cambiar una caracter en una cadena c

int main() 
{ 
    char *c = "hello"; 
    c[3] = 'g'; // segmentation fault here 
    return 0; 
} 

Lo que está haciendo el compilador cuando encuentra char *c = "hello";?

La manera en que yo entiendo, su una serie automática de carbón, y c es un puntero al primer carácter. Si es así, c[3] es como *(c + 3) y debería poder realizar la tarea.

Sólo tratando de comprender la forma en que funciona el compilador.

+2

** las matrices no son punteros ** y ** los punteros no son matrices **. El literal de cadena ('" hello "') es una matriz de 6 caracteres (cuente el terminador nulo). Lea la sección 6 de [comp.lang.c faq] (http://c-faq.com/). Una vez que haya hecho eso, lea las otras secciones también :) – pmg

+4

Duplicado de muchos para enumerar aquí. –

+1

Necesitamos introducir un filtro en el código de la pregunta SO que detecta 'char * XX =" ... "' y proporciona la respuesta allí y luego, en línea en el cuadro de diálogo preguntar pregunta. –

Respuesta

7

hay una diferencia entre estos:

char c[] = "hello"; 

y

char *c = "hello"; 

En el primer caso el compilador asigna espacio en la pila para 6 bytes (es decir, 5 bytes para "Hola" y uno para el terminador nulo

En el segundo caso, el compilador genera una cadena estática const llamada "hola" en un área global (también conocida como cadena literal, y asigna un puntero a la pila que se inicializa para apuntar a esa cadena const.

no puede modificar una cadena constante, y es por eso que está recibiendo una violación de segmento.

+0

En C, un tipo literal de cadena no es 'const char [N]' (con 'N' solo lo suficientemente grande). Los literales de cadena realmente tienen el tipo 'char [N]' pero cambiarlos no está definido. – pmg

+0

@pmg: estoy corregido –

+0

No ha recibido una respuesta correcta, porque no es una solución sobre su respuesta. Quiere cambiar el carácter específico, no hay cambio en otra estructura, y sí es posible :) – delive

8

Las constantes de cadena son inmutables. No puede cambiarlos, aunque los asigne a un char * (así que asígnelos a un const char * para que no los olvide).

Para entrar en más detalle, su código es más o menos equivalente a:

int main() { 
    static const char ___internal_string[] = "hello"; 
    char *c = (char *)___internal_string; 
    c[3] = 'g'; 
    return 0; 
} 

Este ___internal_string a menudo se asignan a un segmento de datos de sólo lectura - cualquier intento de cambiar los datos no se traduce en una caída (estrictamente hablando, también pueden ocurrir otros resultados; este es un ejemplo de "comportamiento indefinido"). Sin embargo, debido a razones históricas, el compilador le permite asignar a char *, lo que le da la falsa impresión de que puede modificarlo.

Tenga en cuenta que si se hizo esto, que funcionaría:

char c[] = "hello"; 
c[3] = 'g'; // ok 

Esto se debe a que estamos inicializar un array de caracteres no constante. Aunque la sintaxis es similar, el compilador la trata de forma diferente.

+2

+1 por * aproximadamente * ... pero en C, un tipo literal de cadena no es 'const char [N]' (con 'N' lo suficientemente grande). Los literales de cadena realmente tienen el tipo 'char [N]' pero cambiarlos no está definido. – pmg

+0

Dije _roughly_ equivalent :) – bdonlan

1

No puede cambiar el contenido de una cadena literal. Necesitas hacer una copia.

#include <string.h> 

int main() 
{ 
    char *c = strdup("hello"); // Make a copy of "hello" 
    c[3] = 'g'; 
    free(c); 
    return 0; 
} 
+0

Vale la pena señalar que el uso de 'char c []' como lo sugieren los otros carteles lo hace menos propenso a errores, ya que no necesita liberar nada. – Staven

Cuestiones relacionadas