数组形参

《C专家编程》一书中的216页有一个很有意思的示例。它形象的展示了数组形参在函数内部是如何作为指针来使用的。

为了简单,稍微简化了一下:

复制代码
代码
#include <stdio.h>

int    ga[10];

void array_fun(int a[])
{
    a[
0= 1;
    printf(
"&a = %#x\n"&a);
    printf(
"&a[0] = %#x\n"&a[0]);
}


int main()
{
    printf(
"&ga = %#x\n"&ga);
    printf(
"&ga[0] = %#x\n"&ga[0]);
    array_fun(ga);
    
    
return 0;
}
复制代码

 

输出结果如下:

&ga = 0x4394b0
&ga[0] = 0x4394b0
&a = 0x12ff30
&a[0] = 0x4394b0

 

为了更好的理解数组形参,下面给出汇编代码(VC 6.0下):

复制代码
代码
7:        a[0] = 1;
00402878   mov         eax,dword ptr [ebp+8]
0040287B   mov         dword ptr [eax],1
8:        printf("&a = %#x\n", &a);
00402881   lea         ecx,[ebp+8]   #实参在栈中的位置(实参本身的内存地址)-->ecx
00402884   push        ecx
00402885   push        offset string "&a = %#x\n" (00432038)
0040288A   call        printf (00404910)
0040288F   add         esp,8
9:        printf("&a[0] = %#x\n", &a[0]);
00402892   mov         edx,dword ptr [ebp+8]  #实参的内容(数组的地址) -->edx,(注意实参本身的地址(通过lea指令获取)与数组地址的差别)
00402895   push        edx
00402896   push        offset string "&a[0] = %#x\n" (00432028)
0040289B   call        printf (00404910)
004028A0   add         esp,8
复制代码

结论:

对数组形参本身取地址,即 &a,则相当于LEA R, [ebp+8]   (R表示寄存器),本质上相当于求参数本身的地址;

而对数组形参的元素取地址,即 &a[n],则相当于MOV R,[ebp+8+n*scale],尽管,这是C的语法,但是不能不看到LEA与MOV的精妙与区别所在。

指针(*),则相当于寄存器间接寻址的MOV;取址(&),则相当于寄存器间接寻址的LEA,如是而已——闲着没事,乱谈一番。

posted @   YY哥  阅读(1189)  评论(1编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
点击右上角即可分享
微信分享提示