参考:
https://blog.csdn.net/bxw1992/article/details/74011951
代码1:
#include <stdio.h> #include <stdlib.h> int test() { g_name[0]='1'; //a[0]=1 g_name[1]='0'; //a[1]=2 g_name[2]='1'; //a[2]=3 g_name[3]=' '; //a[2]=3 printf("define_print() : %s ", g_name); } int main() { test(); return 0; }
运行结果;
define_print() : 101
反汇编如下:
080483c4 <test>: #include <stdio.h> #include <stdlib.h> int test() { 80483c4: 55 push %ebp 80483c5: 89 e5 mov %esp,%ebp 80483c7: 83 ec 28 sub $0x28,%esp char g_name[]="123"; 80483ca: a1 e5 84 04 08 mov 0x80484e5,%eax 80483cf: 89 45 f4 mov %eax,-0xc(%ebp) g_name[0]='1'; //a[0]=1 80483d2: c6 45 f4 31 movb $0x31,-0xc(%ebp) g_name[1]='0'; //a[1]=2 80483d6: c6 45 f5 30 movb $0x30,-0xb(%ebp) g_name[2]='1'; //a[2]=3 80483da: c6 45 f6 31 movb $0x31,-0xa(%ebp) g_name[3]=' '; //a[2]=3 80483de: c6 45 f7 00 movb $0x0,-0x9(%ebp) //p[0]='1'; //a[0]=1 //p[1]='2'; //a[1]=2 //p[2]='3'; //a[2]=3 printf("define_print() : %s ", g_name); 80483e2: b8 d0 84 04 08 mov $0x80484d0,%eax 80483e7: 8d 55 f4 lea -0xc(%ebp),%edx 80483ea: 89 54 24 04 mov %edx,0x4(%esp) 80483ee: 89 04 24 mov %eax,(%esp) 80483f1: e8 fe fe ff ff call 80482f4 <printf@plt> } 80483f6: c9 leave 80483f7: c3 ret 080483f8 <main>: int main() { 80483f8: 55 push %ebp 80483f9: 89 e5 mov %esp,%ebp 80483fb: 83 e4 f0 and $0xfffffff0,%esp test(); 80483fe: e8 c1 ff ff ff call 80483c4 <test> return 0; 8048403: b8 00 00 00 00 mov $0x0,%eax }
可以看出,
char g_name[]="123";
80483ca: a1 e5 84 04 08 mov 0x80484e5,%eax 80483cf: 89 45 f4 mov %eax,-0xc(%ebp)
是把字符串字面量在全局常量区的内容复制到栈中的字符数组。字符串字面量的地址是0x80484e5,字符数组的地址是-0xc(%ebp),在栈中。
代码2,仅仅将代码1中的
char g_name[]="123"改为
char *g_name="123";
运行后发生段错误,
反汇编得到
int test() { 80483c4: 55 push %ebp 80483c5: 89 e5 mov %esp,%ebp 80483c7: 83 ec 28 sub $0x28,%esp char *g_name="123"; 80483ca: c7 45 f4 e0 84 04 08 movl $0x80484e0,-0xc(%ebp) g_name[0]='1'; //a[0]=1 80483d1: 8b 45 f4 mov -0xc(%ebp),%eax 80483d4: c6 00 31 movb $0x31,(%eax) g_name[1]='0'; //a[1]=2 80483d7: 8b 45 f4 mov -0xc(%ebp),%eax 80483da: 83 c0 01 add $0x1,%eax 80483dd: c6 00 30 movb $0x30,(%eax) g_name[2]='1'; //a[2]=3 80483e0: 8b 45 f4 mov -0xc(%ebp),%eax 80483e3: 83 c0 02 add $0x2,%eax 80483e6: c6 00 31 movb $0x31,(%eax) g_name[3]=' '; //a[2]=3 80483e9: 8b 45 f4 mov -0xc(%ebp),%eax 80483ec: 83 c0 03 add $0x3,%eax 80483ef: c6 00 00 movb $0x0,(%eax) //p[0]='1'; //a[0]=1 //p[1]='2'; //a[1]=2 //p[2]='3'; //a[2]=3 printf("define_print() : %s ", g_name); 80483f2: b8 e4 84 04 08 mov $0x80484e4,%eax 80483f7: 8b 55 f4 mov -0xc(%ebp),%edx 80483fa: 89 54 24 04 mov %edx,0x4(%esp) 80483fe: 89 04 24 mov %eax,(%esp) 8048401: e8 ee fe ff ff call 80482f4 <printf@plt> } 8048406: c9 leave 8048407: c3 ret 08048408 <main>: int main() { 8048408: 55 push %ebp 8048409: 89 e5 mov %esp,%ebp 804840b: 83 e4 f0 and $0xfffffff0,%esp test(); 804840e: e8 b1 ff ff ff call 80483c4 <test> return 0; 8048413: b8 00 00 00 00 mov $0x0,%eax }
可以看出
char *g_name="123"; 80483ca: c7 45 f4 e0 84 04 08 movl $0x80484e0,-0xc(%ebp)
是将字符串字面量的地址赋值给了栈中的指针变量g_name;后面通过指针变量g_name访问时,由于修改全局常量区的数据,所以发生段错误。
结论:
注意:
指针方式创建的字符数组,是常量字符串,指针指向的内容是没法更改的;方括号([])方式创建的字符数组仅仅是变量,内容可以更改。