参考:
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]='\0'; //a[2]=3
printf("define_print() : %s\n", 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]='\0'; //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\n", 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]='\0'; //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\n", 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访问时,由于修改全局常量区的数据,所以发生段错误。
结论:
注意:
指针方式创建的字符数组,是常量字符串,指针指向的内容是没法更改的;方括号([])方式创建的字符数组仅仅是变量,内容可以更改。