读书人

可变参函数的兑现

发布时间: 2012-12-28 10:29:04 作者: rapoo

可变参函数的实现

????? 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_startint 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

?

读书人网 >编程

热点推荐