Extraño comportamiento de los punteros 'char'

Cuando declaro y ejecuto lo siguiente, me da un Fallo de segmentación.

main()
{
    char *p = "boa";
    *(p+1) = 'y';
    printf("%s",p);
}

Sospecho char *p es una constante, etc

Pero lo siguiente funciona bien.

main()
{
    int i = 300;
    char *p = (char*)&i;
    *(p+1) = 'y';
    printf("%s",p);
}

Cuál es la razón detrás de esto? ¿La regla anterior no se aplica a esto también?

preguntado el 28 de julio de 12 a las 09:07

3 Respuestas

Eso depende de su definición de "funciona bien". Pero la razón por la que la asignación no falla en la segmentación es porque p se hizo para señalar la dirección de la i variable, que claramente no es una constante. i se le asignó un valor constante, pero i en sí mismo no es una constante.

Para i = 300 (asumiendo little endian x86):

  +--+--+--+--+
i:|2c|01|00|00|
  +--+--+--+--+
  .
 /|\
  |

p:&i

Después *(p+1) = 'y'

  +--+--+--+--+
i:|2c|79|00|00|
  +--+--+--+--+
  .
 /|\
  |

p:&i

Entonces, la declaración de impresión simplemente se imprime ,y para ti, pero solo porque confiaste en el ordenamiento de bytes de la plataforma (y eso 2c era un imprimible ASCII personaje). Las cosas podrían haber sido diferentes en una máquina big endian y/o si no fuera ASCII.

Respondido 29 Jul 12, 13:07

Oh chico...

El primero falla en el segmento debido a que la cadena está const (tienes ese derecho). ¡El segundo, sin embargo, es un abuso fascinante de la semántica de punteros! ;-)

Esto es lo que está haciendo en el segundo ejemplo:

  • tener un azar int número con un valor (en su caso - 300)
  • Consigue una dirección de eso int - básicamente una dirección a una ubicación que contiene un (¿32 bits?) int de 300 y lánzalo a un char*, donde cada elemento apunta a un valor de 8 bits
  • Obtenga la dirección del "primer" valor de 8 bits, incremente en uno (incremente en 8 bits (!)) y cambie el valor de esos 8 bits a un código ASCII numérico de 'y'
  • Imprime la "cadena resultante"

Respondido 28 Jul 12, 09:07

La diferencia es esta:

char *p="boa";

p es un puntero. estas haciendo p apuntar a un literal de cadena "boa" que no se puede modificar y cuando intenta modificarlo se produce un error de segmento.

int i=300;
char *p=(char*)&i;

i es una variable de tipo int, solo usas la constante 300 para inicializar i y hacer una copia bit a bit del valor de 300 en la ubicación de i, pero tu eres nunca apuntando a la constante en sí, solo usándola como un inicializador. Esta es la diferencia, p en su primer ejemplo apunta a un literal de cadena constante, mientras que en su segundo ejemplo apunta a una variable de tipo int. Por lo tanto, modificar la ubicación de i luego con el puntero p está bien porque estás modificando un objeto no constante i.

Respondido 28 Jul 12, 09:07

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.