理解指针

来源:互联网 发布:appium python ios 编辑:程序博客网 时间:2024/04/28 17:44

C语言学习的重点之一就是指针。通过反汇编,能够直接透视指针的本质

指针是什么?指针存储了内存的地址,是一个存储空间,其中存放内存中的地址信息,指针是有类型的,如int*float*

因此,我们猜想指针变量应该存储有这两方面的信息,地址和指针类型,如:

struct pointer{

long address;    //地址

int type;        //指针的类型

};

 

先做一个简单的实验,sizeof(int *)sizeof(float*)实验结果都是4,不是8,这4字节包含的是什么内容呢——32位地址,也就是说,指针变量并没有存储类型信息。那为什么还有指针类型、强制转换……

并且如果不转换,不同类型的指针无法赋值(如int * 赋值给float * 就是错误的)

#include "stdafx.h"

 

int gi;

int *pi;

 

int _tmain(int argc, _TCHAR* argv[])

{

pi = &gi;

*pi = 12;

 

return 0;

}

 

 

 

pi = &gi;

0041138E  mov         dword ptr ds:[00417140h],417144h 

 

gi的地址是0x417144,指针变量pi自身的地址是0x00417140

mov指令将gi地址,放入到指针变量pi中,显然,指针变量确实只有地址信息

难道真的没有类型信息吗?

    指针是用来访问内存的,访问内存,只要地址就可以了吗?显然不是的,还需要知道访问多少字节——类型信息

mov  dword ptr ds:[00417140h],  417144h

mov中的dword ptr(double word),说明要赋值4个字节(0x00417144,而非3个字节),这就是类型信息,指针变量只存储了地址信息,而类型信息,即访存大小信息,存放在mov指令的dword中。到此为止,我们能够发现指针的类型决定了赋值/读取的时候写/读了多少字节。

读写多少字节的信息不是存放在指针变量当中,而是放到了与该地址相关的赋值指令当中,mov指令中的dword指明了这个信息。

C语言之所以要包装出指针的概念,是在汇编地址的内涵上增加另一层含义,即读/写多少字节。不同类型指针,访问字节数不同,int * 访问4个字节,short * 访问两个字节。

这样方便我们操控地址,否则的话,每次访问它还要附加说明访问的字节数。

这时我们也能理解,指针加1减去1都不是加减1字节而是加减相应长度的字节数。

 

*pi = 12;

00411398  mov         eax,dword ptr ds:[00417140h] 

0041139D  mov         dword ptr [eax],0Ch 

 

很明显,在int型的指针pi赋值为12 的时候,由于12也是默认为int型的,很easy

首先将pi指针的地址   保存在eax当中  累加器  然后将0Ch的数值付给dword ptr eax】就可以了

 

疑惑,为什么不是一句mov代码就完成了呢?

明白了第一次是为了获得指针地址当中存储的内容(是目的地址)第二次才是将0Ch写入目的地址对应的内存单元当中去。

立即数不能当中目的地址的,本来就是不能。

00417140h  是pi的地址,dword ptr ds:[00417140h] pi地址当中的内容  并不能当做操作数的,因为并不是我们的目的地址。

 

// 1.5.cpp : 定义控制台应用程序的入口点。

//

 

#include "stdafx.h"

 

short gi;

short *pi;

 

int _tmain(int argc, _TCHAR* argv[])

{

pi = &gi;

*pi = 12;

 

return 0;

}

 

*pi = 12;

00411398  mov         eax,0Ch 

0041139D  mov         ecx,dword ptr ds:[00417140h] 

原创粉丝点击