2019独角兽企业重金招聘Python工程师标准>>>
一.传值
二.传指针(地址)
传地址调用函数顾名思义,就是向被调函数传递的是一个地址值,而不是数据内容,这个地址通常是一个32位无符号整数,表示为十六进制就是形如:0x???? ????,在实际内存中是以(DWORD)形式存放 ,这就是指针类型在内存中通常占用4字节的原因。
有源代码:
void func(int *b){*b=10;
}int main(int argc,char *argv[])
{//call funcint a;func(&a);return 0;
}
这段代码就是通过func函数修改main函数的一个局部变量a。
main函数中对应的汇编码如下所示:
//call func
int a;
func(&a);
00911438 lea eax,[ebp-0Ch]
0091143B push eax
0091143C call 009111D1
00911441 add esp,4
//可以看到,传指针时,有一个lea指令,该指令是将局部变量a的地址也就是ebp-0ch传送给寄存器eax
//然后将eax压栈,换句话说压栈的内容是&a(ebp-0ch)
//后续操作和之前介绍的传值调用一致
为了更直观一些,我们在内存窗口查看这个地址放在哪儿了。然后由这个地址找到a所在内存单元,看是不是0xCCCCCCCC(请参考)
&a=0x0109FEE0
PUSH &a
再看看func函数:
*b=10;
009113EE mov eax,dword ptr [ebp+8]
//从栈底偏移+8处取出调用时push的&a,从内存中也可以看出正好是放在那里的
009113F1 mov dword ptr [eax],0Ah
//注意这里eax存的是&a,作为地址然后找到对应的内存单元,向里面传送10,就是实现了*b=10
内存中是怎么样的呢? 0x0109FEE0处:
可以看到确实变成了0a
和传值调用唯一的不同就是参数压栈时压的是地址而已。
如果需要向函数传一个对象,而这个对象占用很大的一块内存,如果使用传值方式,则需要在被调函数栈底下面(参数表)push一个对象,相当于完全拷贝这个对象,占用同样的内存空间。
而如果使用传指针,那么仅仅需要push一个4字节的地址值而已,对象没有发生拷贝,大大节省了内存和时间。这就是使用指针的高效处。