¿Por qué no debería intentar alterarlo?
Porque es un comportamiento indefinido. Cita del C99 N1256 borrador 6.7.8 / 32 "Inicialización" :
EJEMPLO 8: La declaración
char s[] = "abc", t[3] = "abc";
define objetos de matriz de caracteres "simples" syt cuyos elementos se inicializan con literales de cadena de caracteres.
Esta declaración es idéntica a
char s[] = { 'a', 'b', 'c', '\0' },
t[] = { 'a', 'b', 'c' };
Los contenidos de las matrices son modificables. Por otro lado, la declaración
char *p = "abc";
se define pcon el tipo "puntero a char" y lo inicializa para apuntar a un objeto con el tipo "matriz de char" con longitud 4 cuyos elementos se inicializan con una cadena de caracteres literal. Si se intenta utilizar ppara modificar el contenido de la matriz, el comportamiento no está definido.
¿A dónde van?
GCC 4.8 x86-64 ELF Ubuntu 14.04:
char s[]: apilar
char *s:
.rodata sección del archivo objeto
- el mismo segmento donde se volca la
.textsección del archivo objeto, que tiene permisos de lectura y ejecución, pero no escritura
Programa:
#include <stdio.h>
int main() {
char *s = "abc";
printf("%s\n", s);
return 0;
}
Compilar y descompilar:
gcc -ggdb -std=c99 -c main.c
objdump -Sr main.o
La salida contiene:
char *s = "abc";
8: 48 c7 45 f8 00 00 00 movq $0x0,-0x8(%rbp)
f: 00
c: R_X86_64_32S .rodata
Entonces la cadena se almacena en el .rodata sección.
Luego:
readelf -l a.out
Contiene (simplificado):
Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
[Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
LOAD 0x0000000000000000 0x0000000000400000 0x0000000000400000
0x0000000000000704 0x0000000000000704 R E 200000
Section to Segment mapping:
Segment Sections...
02 .text .rodata
Esto significa que la secuencia de comandos enlazador predeterminado vertederos tanto .texty .rodataen un segmento que se puede ejecutar pero sin modificar ( Flags = R E). Intentar modificar un segmento de este tipo conduce a un defecto en Linux.
Si hacemos lo mismo para char[]:
char s[] = "abc";
obtenemos:
17: c7 45 f0 61 62 63 00 movl $0x636261,-0x10(%rbp)
por lo que se almacena en la pila (en relación con %rbp) y, por supuesto, podemos modificarlo.