指针指向字符串常量和给字符数组赋值字符串常量的本质

    众所周知任何类型的指针在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;
}

指针指向字符串常量和给字符数组赋值字符串常量的本质_第1张图片
指针指向字符串常量和给字符数组赋值字符串常量的本质_第2张图片
本质的原因是因为双引号是一个字符串常量   

 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   

 

你可能感兴趣的:(基本语法,字符串,指针)