可变参函数的实现

      C编译器通常提供了一系列处理这种情况的宏,以屏蔽不同的硬件平台造成的差异,

增加程序的可移植性。这些宏包括va—start、va—arg和va—end等。

 

      这些在stdarg.h中可以找到。

      #define _INTSIZEOF(n) ((sizeof(n)+sizeof(int)-1)&~(sizeof(int) - 1) )

  #define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) ) //第一个可选参数地址

  #define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) ) //下一个参数地址

  #define va_end(ap) ( ap = (va_list)0 ) // 将指针置为无效

 

      为什么可以这么做呢,我们在调用函数的时候,会把函数的参数等信息压入栈空间。

     

      最后一个参数

  倒数第二个参数

  ...

  第一个参数

  函数返回地址

  函数代码段

 

      一般说来从下到上的空间地址值逐渐减小,这个跟平台有关的,不关我们的事,

如果有必要stdarg.h会帮我们处理平台相关的东西。看一个简单的使用例子。

#include <stdio.h>
#include <stdarg.h> //va_start

int sum(int num, ...) {
    va_list parg;
    int arg, s = 0;

    va_start(parg, num);

    for (int i = 0; i < num; ++i) {
        arg = va_arg(parg, int);
        s += arg;
    }
    va_end(parg);
    return s;
}

void addr(int a, int b) {
    printf("a's addr = %x\n", &a);
    printf("b's addr = %x\n", &b);
}
int main(int argc, char* argv[]) {
    addr(5, 6);
    printf("%d\n", sum(3, 5, 2, 9));
    // 5 + 2 + 9 = 16
    return 0;
}

运行结果: 

a's addr = 611a55bc
b's addr = 611a55b8
16

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值