|
5鱼币
- #include <stdio.h>
- #include <stdlib.h>
- int main()
- {
- char *pArray[]={//一个指针数组,存放的指针
- "Hello.",
- "How are you?",
- "Fine,thank you,and you?",
- "I'm fine too."};
-
- char (*p)[4] = &pArray; //一个数组指针,指向pArray这个数组
- //然后这里也有一个warning
- //initialization from incompatible pointer type
-
- printf("%s\n",*p);//一个*的*p表示pArray,数组名不就是首地址吗?,也就是Hello.
- //但为什么运行后什么结果也没有呢?
- //我想的是两个*的**p应该就是pArray[0]
- //但是为什么验证后**p是null呢?
- system("pause");
- return 0;
- }
复制代码
本帖最后由 行客 于 2018-12-26 22:33 编辑
借ba21的代码,我给你从汇编角度分析一下,希望能加深你的理解:
- 6: char *pArray[]={// 指针数组:这个应该明白的吧?结合后面{}内的4个字符串,你可以理解成定义了一个4个char*的数组,就是pArray[0]是一个char *即指向"Hello.",pArray[1]是另一个char*指向"How are you?",后面的两个也一样。
- 7: "Hello.",
- 00401028 mov dword ptr [ebp-10h],offset string "Hello." (00424064) ;这句话的意思是,将"Hello."字符串的首地址00424064放在内存单元[ebp-10h]里;offset string "Hello." 就是指的'H'的地址(00424064)。这里首先要理解"Hello."本身是一个字符串常量,而字符串常量存放在静态存储区(你可以暂时理解为,有一个专门的地方用来存放各个字符串的,这个字符串的地址,如果没有通过编译器(IDE开发环境,就是类如VC6\VC2010等等的IDE编译工具))重新构建编译,这个字符串的地址是不变的)。C语言中的字符串常量以第一个字符的存放地址作标记,它本身就是一个地址常量(这里是00424064),这个地址常量只能作“指针右值”。也就是'H'这个字符的地址常量(00424064)就是这个字符串的标志,这个标志就是一个内存单元的地址(00424064),我们的编译器没办法直接用这个内存地址(00424064)作为代号(即变量名)来和我们开发者交互的,因为每次重新构建编译,这个地址是会发生改变的。所以这个地址(00424064)只能作为指针右值。而这个右值可以赋给一个“同类型”的“指针”。注意这里,我所说的同类型指针是包含了两个部分的,一个是指针,一个是同类型。所谓“指针”,也只是编译器定义了一个可以和我们开发者可以互相沟通的符号,其实也只是一个变量名,只是这个变量名(变量名代表的是一个地址)里存放的是我们字符串的地址,而在这里这个地址指向了字符串。所谓“同类型”,其实对于计算机底层来讲,指针本身是不分类型的,指针里面放的就是一个地址;同类型是编译器的概念,编译器就是将我们所定义的符号、语句编译成汇编,最终再链接成exe;同类型要解决的是能让编译器能识别数据宽度而能达到我们想要的编译结果的问题。在32位WIN的VS编译器默认情况下,指针存放地址(如(00424064))的内存单元的数据宽度为4字节,也就是dword宽度。那么指针本身的数据宽度为4字节。这里可以使用“printf("%d\n",sizeof(pArray[0]));”看一下结果验证。那么这个指针是怎么识别字符串长度的呢,字符串最后有一个我们看不到结束符为"\0"(内存中为16进制00),所以遇到"\0"后,就结束了。那么好,到这里我们可以继续往下看了:
- 8: "How are you?",
- 0040102F mov dword ptr [ebp-0Ch],offset string "How are you?" (00424054) ;将"How are you?" 的首地址放在[ebp-0Ch]单元,以下类同
- 9: "Fine,thank you,and you?",
- 00401036 mov dword ptr [ebp-8],offset string "Fine,thank you,and you?" (00424038)
- 10: "I'm fine too."};
- 0040103D mov dword ptr [ebp-4],offset string "I'm fine too." (00424028)
- 11:
- 12: char *(*p)[4] = &pArray; //数组指针,你上面的变量pArray的类型是char *[],同时后面{}内确定了是4个元素,所以定义指针需要定义为char *(*p)[4]
- 00401044 lea eax,[ebp-10h] ;将[ebp-10h]的地址放在eax。。
- 00401047 mov dword ptr [ebp-14h],eax ;将[ebp-10h]的地址通过eax又放在了[ebp-14h]里
- 13:
- 14: printf("%s\n",**p);// 1层解引用行的地址,再次解引用,该行第1个元素的地址
- 0040104A mov ecx,dword ptr [ebp-14h] ;
- 0040104D mov edx,dword ptr [ecx] ;
- 0040104F push edx
- 00401050 push offset string "%s\n" (00424024)
- 00401055 call printf (004011b0)
- 0040105A add esp,8
复制代码
|
最佳答案
查看完整内容
借ba21的代码,我给你从汇编角度分析一下,希望能加深你的理解:
|