可变参数列表

  有的时候同一个函数核可能需要接收不同数量的参数,那么函数原型应该如何定义,不确定的参数应该如何访问,下面将给出答案。

可变参数列表是通过宏来实现的,这些宏定义于stdarg.h的头文件中,它声明了一种类型 va_list(typedef __builtin_va_list __gnuc_va_list; 头文件中是这样定义的) 和三个宏 ---- va_start va_arg 和 va_end (

#define va_start(v,l)    __builtin_va_start(v,l)
#define va_end(v)    __builtin_va_end(v)
#define va_arg(v,l)    __builtin_va_arg(v,l)

)。通过使用一个类型和三个宏配合我们就可以访问到参数的值。

当然实际的程序这样写是没有必要的,只要用数组就好了,但是在这里为了举一个简单的例子就使用了这种方法,假如我们要写一个求和的代码,但是不使用数组,那么我们就不一定向函数中传递多少参数,那么我们就需要这样写。

如下代码:

#include<stdio.h>
#include<stdarg.h>
int sum(int n,...);

int main()
{
    int a;
    a=sum(4,1,2,3,4);
    printf("%d",a);
}

int sum(int n,...)
{
    int i;
    int sum=0;
    va_list var_arg;
    va_start(var_arg,n);
    for( i = 0; i < n ; i++ )
    {
        sum+=va_arg( var_arg , int );
    }
    va_end(var_arg);
    return sum;
}

所有的可变参数和函数在定义的时候不确定部分就用用 “...” 来补充他们的位置,那么函数原型就如int sum(int n,...);

当然实际使用的时候肯定不会只是这样的简单的参数,可变参数部分可能会接收int short char这些都会转换成 int类型 , float 会转换为 double 类型,编译器和宏并不会帮你分析传递的参数的类型,这就需要你自己经过一些判断来分析传递的参数类型并进行强制转换。在函数接收了传递来的参数的时候我们并不知道这些参数的名称,这个时候我们就需要用到头文件stdarg.h 的一个类型和三个宏,那么首先在函数中你需要定义一个 va_list 类型的变量,如 va_list var_arg; ,这个var_arg变量就是用来访问未确定的部分,同时这个变量需要通过 va_start 来进行初始化,va_start 有两个参数第一个参数是va_list类型的变量的名称,第二个参数是未确定参数之前的最后一个有名字的参数。初始化过程把var_arg变量设置为指向可变参数的部分的第一个参数。初始化后我们就需要进行访问这些参数,这时需要使用 va_arg,这个宏也有两个参数,va_list 类型的变量和参数的类型,如:sum+=va_arg( var_arg , int ); ,va_arg( var_arg , int )  会返回一个未确定的参数并指向下一个未确定的参数,当然这些参数都是需要你进行一些判断的,可能是前面的一些承参数提供给你的信息。就像在定义一个文件文件指针一样,在对它操作结束后就需要对它进行释放,因为C语言中没有垃圾处理机制,这一切的工作都需要我们自己来完成,请一定要记住定义后就一定要有对应的释放,不然这些没有用的东西没有得到释放,那么及时你的内存再大也有不够用的一天,同时即使i你的内存够用这也是一种浪费的行为,当然可变参数列表也不会例外的,它使用 va_end 只有一个参数就是 va_list 类型的变量,如代码中:va_end(var_arg); 

 

当然可变参数列表本身也存在一些问题,就行刚才的程序你就可以看出,如果你想中途停止访问这些未知参数是可以的,但是如果你想不从头访问,直接访问其中的某一个肯定是不可以的。

原文地址:https://www.cnblogs.com/foreverW/p/7242100.html