C语言函数参数数量不同、参数为变参时参数的传递规则

写这篇笔记是因为对C语言函数参数的传递突然有了很多疑惑。ATPCS规定R0~R4用于存储前四个参数,那么如果对前四个参数取址得到的是什么结果呢?CPU的寄存器是自有的,不在内存空间中。如果要实现变参函数,找不到参数的入口地址,那接下来的工作就无法完成。于是写了一些代码,做了一些实验来寻找答案。代码在ARM和MSP430芯片上通过运行。

结论

   (1) 参数数量固定, 并且参数数量小于等于4个.

      参数会从左到右传到R0~R3寄存器中, 同时在内存中会有这些参数的副本, 并且参数按从左到右依次占据内存从高地址到低地址的连续空间.

   (2) 参数数量固定, 并且参数数量大于等于5个

      前四个参数的行为同(1), 从第5个参数到后面所有参数, 按从左到右依次占据内存从低址到高地址的连续空间.

   (3) 参数数量不固定

      原则: 最后一个固定参数的相邻高地址空间开始存放变参, 并且变参按从左到右依次占据内从从低地址到高地址的连续空间.

      对于其余固定参数, 优先传到R0~R3, 而内存中也会存有这些参数的副本, 从高地址到低地址连续存储; 当R0~R3不够用时, 继续将参数从低地址到高地址存储到内存中, 直到和最后一个固定参数相邻.

 

   P.S. 在函数中获取参数的地址, 得到的是其在内存中的地址, 对于需要传进R0~R3的参数, 则是其在内存中副本的地址.

 

实验

(一) 使用arm-linux-gnueabihf-gcc编译, 在imx6ull上运行. IMX6ULL是32位单片机, int类型数据占4个字节, 指针类型占4个字节.

 

#include "stdio.h"
int func_va_list(int a, int b, int c, int d, int e, int f, ...){
    int *p;
    p = (int*)&a;
    printf("&a = 0x%8x, p= 0x%8x, p_a = %d, a = %d\n", &a, p, *p, a);
    p--;printf("p--\n");
    printf("&b = 0x%8x, p= 0x%8x, p_b = %d, b = %d\n", &b, p, *p, b);
    p--;
    printf("&c = 0x%8x, p= 0x%8x, p_c = %d, c = %d\n", &c, p, *p, c);
    p--;
    printf("&d = 0x%8x, p= 0x%8x, p_d = %d, d = %d\n", &d, p, *p, d);
    p--;
    printf("&e = 0x%8x, p= 0x%8x, p_e = %d, e = %d\n", &e, p, *p, e);
    p--;
    printf("&f = 0x%8x, p= 0x%8x, p_f = %d, f = %d\n", &f, p, *p, f);
    p--;
    printf("p= 0x%8x, p_g = %d\n", p, *p);
    return a+f;
}

int func_va_list2(int a, ...){
    int *p;
    p = (int*)&a;
    printf("p= 0x%8x, p_a = %d\n", p, *p);
    p++;printf("p++\n");
    printf("p= 0x%8x, p_b = %d\n", p, *p);
    p++;
    printf("p= 0x%8x, p_c = %d\n", p, *p);
    p++;
    printf("p= 0x%8x, p_d = %d\n", p, *p);
    p++;
    printf("p= 0x%8x, p_e = %d\n", p, *p);
    p++;
    printf("p= 0x%8x, p_f = %d\n", p, *p);
    p++;
    printf("p= 0x%8x, p_g = %d\n", p, *p);
    return a+(*p);

}

int func_va_list3(int a, int b, ...){
    int *p;
    p = (int*)&a;
    printf("p= 0x%8x, p_a = %d, &a = 0x%8x\n", p, *p, &a);
    p++;printf("p++\n");
    printf("p= 0x%8x, p_b = %d, &b = 0x%8x\n", p, *p, &b);
    
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值