分析指针、地址、引用之间的关系;
地址:在C++中地址使用十六进制表示。取一个变量的地址使用"&"符号,只有变量才存在内存地址,常量没有地址
指针:指针的定义使用"Type*",Type为数据类型。任何数据类型都可以定义指针。指针本身也是一种数据类型,它用于保存各种数据类型在内存中的地址,指针变量同样可以取出地址,所以会出现多级指针;
引用:引用定义使用"Type&",Type为数据类型。 在C++中是不可以单独定义的,并且在定义时就要进行初始化。
各类型指针的工作方式;
1.访问同一块地址:2.指针的寻址方式:
//以指针保存的地址作为寻址[首地址],加上偏移量,最终得到目标地址;
//偏移量的计算方式为指针类型长度乘以移动次数,因此得出指针寻址公式如下:
/*type*p; //这里用type泛指某类型的指针;
p+n的目标地址=首地址+sizeof(指针类型 type)*n;在偏移量为赋值的情况下可以使用;
*/
//指针之间可以做减法,得到的差是指两地址之间的元素个数,指针之间不能做其他运算,并且做减法运算指针的类型必须一致:
//公式如下: type*p,q; p-q=((int)p-(int)q)/sizeof(指针类型type);
可以看出引用类型和指针类型没有区别;
地址:在C++中地址使用十六进制表示。取一个变量的地址使用"&"符号,只有变量才存在内存地址,常量没有地址
指针:指针的定义使用"Type*",Type为数据类型。任何数据类型都可以定义指针。指针本身也是一种数据类型,它用于保存各种数据类型在内存中的地址,指针变量同样可以取出地址,所以会出现多级指针;
引用:引用定义使用"Type&",Type为数据类型。 在C++中是不可以单独定义的,并且在定义时就要进行初始化。
各类型指针的工作方式;
1.访问同一块地址:2.指针的寻址方式:
//访问同一块地址;
int nVar = 0x12345678;
int *pnVar = &nVar;
char *pcVar = (char*)&nVar;
short *psnVar = (short*)&nVar;
printf("%08x \r\n", *pnVar);
printf("%08x \r\n", *pcVar);
printf("%08x \r\n", *psnVar);
mov dword ptr[nVar] ,123456789h; //将123456789的数值存放到nVar变量对应的内存中;
lea eax , [nVar] //取nVar变量的地址值赋值给eax寄存器;
mov dword ptr[pnVar] , eax; //将eax存放的地址值赋值给pnVar变量对应的内存中;
lea eax, [nVar];
mov dword ptr[pcVar], eax;
lea eax , [nvar];
mov dword ptr[psnVar], eax;
mov eax,dword ptr[pnVar]; //将ptr[pnVar]存放的nVar的地址移动到eax寄存器;
mov ecx,dword ptr[eax]; //取出对应地址内存存储值移动到寄存器;
push ecx; //参数入栈;
push offset string "%08x \r\n" (0F20EECh)
call @ILT+4415(_printf) (0ECB144h)
mov eax dword ptr[pcVar]; //取得存放的地址值;
mosx ecx byte ptr[eax];
push ecx;
push offset string "%08x \r\n" (0F20EECh)
call @ILT+4415(_printf)(0ECB144h)
mov eax dword ptr[psnVar];
mosx ecx word ptr[eax];
push ecx;
push offset string "%08x \r\n"(0F20EECh)
call @ILT+4415(_printf)(0ECB144h)
//指针的寻址方式:如下代码演示了不同类型指针加1偏移。它们偏移后的地址都是由指针类型决定的,
//以指针保存的地址作为寻址[首地址],加上偏移量,最终得到目标地址;
//偏移量的计算方式为指针类型长度乘以移动次数,因此得出指针寻址公式如下:
/*type*p; //这里用type泛指某类型的指针;
p+n的目标地址=首地址+sizeof(指针类型 type)*n;在偏移量为赋值的情况下可以使用;
*/
//指针之间可以做减法,得到的差是指两地址之间的元素个数,指针之间不能做其他运算,并且做减法运算指针的类型必须一致:
//公式如下: type*p,q; p-q=((int)p-(int)q)/sizeof(指针类型type);
char cvar[5] = {0x01, 0x23, 0x45, 0x67, 0x89};
int *pnVar = (int*)cVar;
char *pcVar = (char*)cVar;
short *psnVar = (short*)cVar;
pnVar += 1;
pcVar += 1;
psnVar += 1;
printf("%08x \r\n", *pnVar);
printf("%08x \r\n", *pcVar);
printf("%08x \r\n", *psnVar);
mov byte ptr[ebp-1Ch],1; //数组从低地址到高地址初始化;
mov byte ptr[ebp-1Bh],23h;
mov byte ptr[ebp-1Ah],45h;
mov byte ptr[ebp-19h],67h;
mov byte ptr[ebp-18h],89h;
lea eax,[ebp-1Ch]; //取出ebp-1Ch处的地址到寄存器;
mov dword ptr[ebp-28h] , eax; //将对应的寄存器的地址赋值给变量pnVar存放的内存中;
lea eax,[ebp-1Ch];
mov dword ptr[ebp-34h] ,eax;
lea eax, [ebp-1Ch];
mov dword ptr[ebp-40h],eax;
//下面描述指针加法的过程;
mov eax,dword ptr[ebp-28h];
add eax,4;
mov dword ptr[ebp-28h],eax;
mov eax,dword ptr[ebp-34h];
add eax,1;
mov dword ptr[ebp-34h], eax; //指针内存存放的地址;
mov eax,dword ptr[ebp-40h];
add eax,2;
mov dword ptr[ebp-40h], eax; //指针内存的地址加2;
//如下为打印汇编;
mov eax, dword ptr[ebp-28h];
mov ecx, dword ptr[eax];
push ecx;
push offset string "%08x \r\n" (0F0DEECh);
call @ILT+4365(_printf)(0EBA112h)
add esp+8;
mov eax, dword ptr[ebp-34];
mov ecx, dword ptr[eax];
push ecx;
push offset string "%08x \r\n" (0F0DEECh);
call @ILT+4365(_printf)(0EBA112h)
add esp+8;
mov eax, dword ptr[ebp-40h];
mov ecx, dword ptr[eax];
push ecx;
push offset string "%08x \r\n" (0F0DEECh);
call @ILT+4365(_printf)(0EBA112h)
add esp+8; //将栈顶地址增加参数个数对应的地址增值;
引用其实就是指,实际上C++为了简化指针操作,对指针的操作进行了封装,产生了引用类型。实际上引用类型就是指针类型,只不过它用于存放地址的内存空间对使用者而言是隐藏的;意思就是type*p;我能知道p对应的内存空间;也能知道p中存放的地址;但是type&p=q;只能知道p存放的地址;看不到p的任何信息;
可以看出引用类型和指针类型没有区别;
int nVar = 0x12345678;
//引用类型定义
int &nVarTpye = nVar;
Add(nVarTpye); //自增函数;
mov dword ptr [nVar],12345678h
lea eax , [nVar];
mov dword ptr[nVarTpye],eax;
mov eax,dword ptr [nVarTpye]
push eax
call Add (1409E01h);
add esp,4