指针指向字符串常量和给字符数组赋值字符串常量的本质
众所周知任何类型的指针在32位模式下大小都为4BYTE,很多人对数组和指针并不能很好的区分它们的区别,首先在C语言层面,数组名是一个常量不可修改,而指针可以随意指向,其次如果在a.cpp中定义了
char a[100]; 的全局变量
在main.cpp中声明了一个 extern char*a ; 有些变成经验的人就能看出来 cha a[100] 开辟的空间是 100*int类型的大小
而extern char* a告诉编译器 有一个 a类型是 char* 大小是4字节,代表的含义完全不同,但是指针的数组什么的汇编代码的引用的方式完全相同,就是汇编层面完全无法区别数组和指针,它们在汇编层次我认为是完全一致的,没有任何区别,这就是汇编封装成C让我写代码更加简便,但是编译器也限制了一些东西
在初学c语言的时候 我只知道 下面这样的形式如果想修改p所指向的内容会挂0xC00000005,而这样操作数组就完全没有问题可读可写
int main(int argc, char* argv[])
{
char* p="taolaoda!helloworld";
char a[]="taolaoda!helloworld";
getchar();
return 0;
}
本质的原因是因为双引号是一个字符串常量
char* p是指向这个字符串常量的地址,指向了常量区只读
"taolaoda!helloworld"字符串常量的长度是20BYTE
8:
9: char* p="taolaoda!helloworld";
0040DDD8 mov dword ptr [ebp-4],offset string "taolaoda!helloworld" (00422fac) p指向了"taolaoda!helloworld"(00422fac)
10: char a[]="taolaoda!helloworld";
0040DDDF mov ecx,5
0040DDE4 mov esi,offset string "taolaoda!helloworld" (00422fac) 这行代码是得到 "taolaoda!helloworld"常量首地址
0040DDE9 lea edi,[ebp-18h] 这行代码是得到数组的首地址报错到edi
0040DDEC rep movs dword ptr [edi],dword ptr [esi]
这行代码是copy 把esi的内容copy到edi每次四字节 copy ecx寄存器里面存储数值的次数这里是5
5*4=20BYTE正好把常量区的 "taolaoda!helloworld"复制到了栈中 char a[]分配的内存中所以可以随意修改 a数组里面的数据,而修改p指向的内容了挂了,这就是本质
char* p在栈中开辟了4个byte的内存 在栈中的地址是 ebp-4
chaar a[20]在栈中开辟了20byte的内存 在栈中首地址是ebp-0x18 ==ebp-24