Mengapa saya tidak mencoba mengubahnya?
Karena itu perilaku yang tidak terdefinisi. Kutipan dari C99 N1256 draft 6.7.8 / 32 "Inisialisasi" :
CONTOH 8: Deklarasi
char s[] = "abc", t[3] = "abc";
mendefinisikan objek char array "polos" s
dan t
yang elemennya diinisialisasi dengan literal karakter string.
Deklarasi ini identik dengan
char s[] = { 'a', 'b', 'c', '\0' },
t[] = { 'a', 'b', 'c' };
Isi array dapat dimodifikasi. Di sisi lain, deklarasi
char *p = "abc";
mendefinisikan p
dengan tipe "pointer to char" dan menginisialisasi untuk menunjuk ke objek dengan tipe "array of char" dengan panjang 4 yang elemennya diinisialisasi dengan karakter string literal. Jika upaya dilakukan untuk digunakan p
untuk mengubah konten array, perilaku tersebut tidak ditentukan.
Kemana mereka pergi?
GCC 4.8 x86-64 ELF Ubuntu 14.04:
char s[]
: tumpukan
char *s
:
.rodata
bagian dari file objek
- segmen yang sama di mana
.text
bagian dari file objek akan dibuang, yang memiliki izin Baca dan Exec, tetapi tidak Tulis
Program:
#include <stdio.h>
int main() {
char *s = "abc";
printf("%s\n", s);
return 0;
}
Kompilasi dan dekompilasi:
gcc -ggdb -std=c99 -c main.c
objdump -Sr main.o
Output berisi:
char *s = "abc";
8: 48 c7 45 f8 00 00 00 movq $0x0,-0x8(%rbp)
f: 00
c: R_X86_64_32S .rodata
Jadi string disimpan di .rodata
bagian tersebut.
Kemudian:
readelf -l a.out
Berisi (disederhanakan):
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
Ini berarti bahwa skrip linker default membuang keduanya .text
dan .rodata
ke dalam segmen yang dapat dieksekusi tetapi tidak dimodifikasi ( Flags = R E
). Mencoba untuk memodifikasi segmen seperti itu mengarah ke segfault di Linux.
Jika kami melakukan hal yang sama untuk char[]
:
char s[] = "abc";
kami memperoleh:
17: c7 45 f0 61 62 63 00 movl $0x636261,-0x10(%rbp)
jadi itu disimpan dalam tumpukan (relatif terhadap %rbp
), dan tentu saja kita dapat memodifikasinya.