C语言可变参函数的实现

1 C语言中函数调用的原理

函数是大多数编程语言都实现的编程要素,调用函数的实现原理就是:执行跳转+参数传递。对于执行跳转,所有的CPU都直接提供跳转指令;对于参数传递,CPU会提供多种方式,最常见的方式就是利用栈来传递参数。C语言标准实现了函数调用,但是却没有限定实现细节,不同的C编译器厂商可以根据底层硬件环境自行确定实现方式。

函数调用的一般实现原理,请参考我的博文 C语言中利用setjmp和longjmp做异常处理中的第一段。

2 可变参实现思路

2.1 如何取得后续实参地址

我们以X86架构上的VC++编译器为例进行举例说明。例子代码如下。

void f(int x, int y, int z)
{
    printf("%p, %p, %p\n", &x, &y, &z);
}
int main()
{
    f(100, 200, 300);
    return 0;
}

可能的执行结果:

00FFF674, 00FFF678, 00FFF67C

VC++中函数的参数是通过堆栈传递的,参数按照从右向左的顺序入栈。调用f时参数在堆栈中的情况如下图所示:
这里写图片描述

可见,我们只要知道x的地址,就可以推算出y,z的地址,从而通过其地址取得参数y,z的值,而不用其参数名称取值。如下代码所示。

void f(int x, int y, int z)
{
    char* px = (char*)&x;
    char *py = px + sizeof(x);
    char *pz = py + sizeof(int);

    printf("x=%d, y=%d, z=%d\n", x, *(int*)py, *(int*)pz);
}
int main()
{
    f(100, 200, 300);
    return 0;
}

可见根据函数的第一个参数,以及后续参数的类型,就可以根据偏移量计算出后续参数的地址,从而取得后续参数值。
于是可以把上述代码改写成可变参数的形式。

void f(int x, ...)
{
    char* px = (
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值