现在的位置: 首页 > 综合 > 正文

数组形参

2012年07月19日 ⁄ 综合 ⁄ 共 1258字 ⁄ 字号 评论关闭

《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,如是而已——闲着没事,乱谈一番。

抱歉!评论已关闭.