首页
社区
课程
招聘
[旧帖] 指针与数组本质 0.00雪花
发表于: 2009-3-21 20:08 3961

[旧帖] 指针与数组本质 0.00雪花

2009-3-21 20:08
3961
算是自己的指针与数组本质的学习笔记吧.发出来给大家分享一下.如有错误,大牛们就指导一下吧.

看代码的时候看见一段没怎么看明白的代码..:
 
unsigned int *PageDirectoryEntry=(unsigned int *)0xC0300000;
.......
.......
PageDirectoryEntry[i]&0xFFFFF000


PageDirectoryEntry[i]这个能想明白,但是好像还不是真正的懂.(就是自己还不能明白其奇妙之处..) 于是又看了看数组与指针..
谭爷爷的书里:
 
int a[]={1,0,2,3};
int *p;
p=a;
for (int i=0;i<=3;i++)
 {
   printf("%d",p[i]);
 }

那上面的就是强制的把*PageDirectoryEntry转成了一个起始地址为0xC0300000的指针数组了.
PageDirectoryEntry[i]就容易明白了.

资料上是这么说的:
1、指针的本质是一个与地址相关的复合类型,它的值是数据存放的位置(地址);
数组的本质则是一系列的变量。
2、数组名对应着(而不是指向)一块内存,其地址与容量在生命期内保持不变,
只有数组的内容可以改变。指针可以随时指向任意类型的内存块,它的特征是“可
变”,所以我们常用指针来操作动态内存。
3、当数组作为函数的参数进行传递时,该数组自动退化为同类型的指针。


这样我自己有动手实践了一下:
[FONT=Arial][COLOR=black][COLOR=black][FONT=Arial]#include "stdafx.h"[/FONT][/COLOR]
[COLOR=black][FONT=Arial]int main(int argc, char* argv[])[/FONT][/COLOR]
[FONT=Arial][COLOR=black]{[/COLOR][/FONT]
[FONT=Arial][COLOR=black]char a[] = "Hi,ABC!";[/COLOR][/FONT]
[FONT=Arial][COLOR=black]char *p = "Hi,ABC!";[/COLOR][/FONT]
[FONT=Arial][COLOR=black]for (int i=0;i<=7;i++)[/COLOR][/FONT]
[FONT=Arial][COLOR=black]{[/COLOR][/FONT]
[FONT=Arial][COLOR=black]printf("%c%c\n",a[i],p[i]);[/COLOR][/FONT]
[FONT=Arial][COLOR=black]}[/COLOR][/FONT]
 
[FONT=Arial][COLOR=black]return 0;[/COLOR][/FONT]
[FONT=Arial][COLOR=black]}[/COLOR][/FONT]
[/COLOR][/FONT]


在VC中反汇编为(看过天书的人应该比较熟悉吧):
6:    int main(int argc, char* argv[])
7:    {
00401010   push        ebp
00401011   mov         ebp,esp
00401013   sub         esp,50h
00401016   push        ebx
00401017   push        esi
00401018   push        edi
00401019   lea         edi,[ebp-50h]
0040101C   mov         ecx,14h
00401021   mov         eax,0CCCCCCCCh
00401026   rep stos    dword ptr [edi]    //处理局部空间的初始化
8:         char a[] = "Hi,ABC!";          //我们看看是怎么对数组a的处理的
00401028   mov         eax,[string "Hi,ABC!" (00422024)] //把a的前4项:Hi,A 的ASCII码保存在了eax ,下面又把它放在了局部变量空间里面
0040102D   mov         dword ptr [ebp-8],eax
00401030   mov         ecx,dword ptr [string "Hi,ABC!"+4 (00422028)] //后3项的处理(为了CPU取数据快些,变量都是存放在偶数内存空间的)
00401036   mov         dword ptr [ebp-4],ecx
9:         char *p = "Hi,ABC!";        //我们看看对于指针的处理,offset明白了吧,是把字符窜的地址存放在局部空间里
00401039   mov         dword ptr [ebp-0Ch],offset string "Hi,ABC!" (00422024)
10:       for (int i=0;i<=7;i++)             
00401040   mov         dword ptr [ebp-10h],0
00401047   jmp         main+42h (00401052)
00401049   mov         edx,dword ptr [ebp-10h]
0040104C   add         edx,1
0040104F   mov         dword ptr [ebp-10h],edx
00401052   cmp         dword ptr [ebp-10h],7
00401056   jg          main+6Ah (0040107a)
11:       {
12:       printf("%c%c\n",a[i],p[i]);     //下面是重点了,数组与指针的不同
00401058   mov         eax,dword ptr [ebp-0Ch] //指针p的值
0040105B   add         eax,dword ptr [ebp-10h] //p+1
0040105E   movsx       ecx,byte ptr [eax]     [COLOR=red]//这个是理解的关键,需要再一次取地址转换,才能得到字符串的值!![/COLOR]
00401061   push        ecx
00401062   mov         edx,dword ptr [ebp-10h]  //i的值
00401065   movsx       eax,byte ptr [ebp+edx-8]//从a的位置开始,向后移动i个字节,然后取出其中的字符。
0040106A   push        eax
0040106B   push        offset string "%c%c\n" (0042201c)
00401070   call        printf (004010b0)
00401075   add         esp,0Ch
13:       }
00401078   jmp         main+39h (00401049)
14:
15:       return 0;
0040107A   xor         eax,eax
16:   }


那么指针和数组的本质区别:
内存布局分别:
  数组a需要在内存中占用8个字节的空间,这段内存区通过名字a来标志。指针p则需要4个字节的空间来存放地址,这4个字节用名字p来标志。其中存放的地址几乎可以指向任何地方,也可以哪里都不指,即空指针。目前这个p指向某地连续的8个字节,即字符串“Hi,ABC!”。
  另外,例如:对于a[1]和p[1],二者都返回字符‘i’,但是编译器产生的执行代码却不一样。对于a[1],执行代码是从a的位置开始,向后移动1两个字节,然后取出其中的字符。对于p[1],执行代码是从p的位置取出一个地址,在其上加1,然后取出对应内存中的字符。


[课程]Linux pwn 探索篇!

收藏
免费 0
支持
分享
最新回复 (5)
雪    币: 190
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
谢谢楼主分享!
2009-3-21 20:24
0
雪    币: 142
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
谢谢楼主分享
2009-3-22 17:57
0
雪    币: 156
活跃值: (48)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
4
呵呵 不错!
我不是大牛菜鸟一个胡说上两句,
是不是 只有c是这样的? 应该限定一下,和编译器有关系。
忘了哪位大牛说过,只要占的字节一样大,都可以看成一个数据类型。
2009-3-23 08:38
0
雪    币: 11
活跃值: (12)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
我不是大牛 也胡乱附和LS两句

汇编只有分byte word和dword三种类型,例如32位下int和long就是dword,大概可以认为其实是一种数据类型吧
2009-3-23 13:32
0
雪    币: 349
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
汇编不是还有qword和tword类型么
2009-3-23 16:21
0
游客
登录 | 注册 方可回帖
返回
//