可变长参数函数

可变长参数函数的参数数量可变。如printf,scanf等函数都是可变长参数函数。
对C语言来说,实现可变长参数函数要用到三个宏:va_start(),va_end(),va_arg()和一个特殊类型va_list,他们被包含在stdarg.h中。
void va_start(va_list ap, T last):初始化函数
void va_end(va_list ap);释放ap所占的内存
type va_arg(ap,type);每次调用va_arg都会修改用va_list声明的对象,从而使该对象指向参数列表中的下一个参数;
举例说明:

#include<iostream>
#include<cstdarg>

int ADD(int num, ...);

int main()
{

    int a = ADD( 3, 4, 5, 6);
    std::cout << a << std::endl;
    getchar();
}

int ADD(int num, ...)
{
    va_list ap;
    va_start(ap, num);
    int sum = 0;
    int temp;
    for (int i = 0; i < num; i++)
    {
        temp = va_arg(ap,int);
        sum += temp;
    }
    va_end(ap);
    return sum;
}

对于可变长参数的实现的要求为:
1.C语言中,函数的参数都会传递到函数所对应的栈里面,而且参数是存放在连续的栈空间的。
2.对于参数进栈,C语言的顺序是从右往左进入栈,栈的增长方向是从上向下,所以参数的地址是从左往右顺序增长的。

验证这个想法,做如下程序,进行一般的可变参数函数的实现:

#include<iostream>
#include<cstdarg>


int ADD(int num, ...);

int main()
{

    int a = ADD( 3, 4, 5, 6);
    std::cout << a << std::endl;
    getchar();

}


int ADD(int num, ...)
{
    int sum = 0;
    int *p=0;
    int temp;
    p = &num + 1;
    for (int i = 0; i < num; i++)
        sum += *(p++);

    return sum;
}

得到的结果和上面一样。

注意点:
1.type va_arg(ap,type)
type不能是:
—— char、signed char、unsigned char
—— short、unsigned short
—— signed short、short int、signed short int、unsigned short int
—— float

在C语言中,调用一个不带原型声明的函数时,调用者会对每个参数执行“默认实际参数提升。可变长参数函数用...代替函数变量声明,所以会做这种参数提升。即:
float类型的实际参数将提升到double
char、short和相应的signed、unsigned类型的实际参数提升到int

版权声明:本文为博主原创文章,未经博主允许不得转载。

posted @ 2015-05-13 18:37  fang92  阅读(323)  评论(0)    收藏  举报