va_list,va_start,va_end处理不定参数函数调用不定参数函数的问题

来源:互联网 发布:linux 修改北京时间 编辑:程序博客网 时间:2024/05/16 13:58

下面是 <stdarg.h> 里面重要的几个宏定义如下:

typedef char* va_list;

void va_start ( va_list ap, prev_param ); /* ANSI version */

type va_arg ( va_list ap, type ); 

void va_end ( va_list ap ); 

不定参数的基本用法概括而言,主要是应用va_list 变量 ,由va_start 初始化,

并通过va_arg获取参数内容,然后应用相应的参数,例如:

   int max(int n, ...) {                // 定参 n 表示后面变参数量,定界用,输入时切勿搞错
 va_list ap;                         // 定义一个 va_list 指针来访问参数表
     va_start(ap, n);                       // 初始化 ap,让它指向第一个变参,n之后的参数
    int maximum = -0x7FFFFFFF;          // 这是一个最小的整数
    int temp;
     for(int i = 0; i < n; i++) {
    temp = va_arg(ap, int);          // 获取一个 int 型参数,并且 ap 指向下一个参数
    if(maximum < temp) maximum = temp;
     }
    va_end(ap);                         // 善后工作,关闭 ap
    return max;
}

va_start使argp指向第一个可选参数。va_arg返回参数列表中的当前参数并使argp指向参数列表中的下一个参数。

va_end把argp指针清为NULL。函数体内可以多次遍历这些参数,但是都必须以va_start开始,并以va_end结尾。

在学习unix环境高级编程的过程中,一直遇到一个err_quit的函数,想到不定参数函数就不尽试了一下,错误代码

如下

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>
#include <stdarg.h>

void err_quit2(char *msg, ...)
{
    va_list args;
    va_start(args,msg);
    printf(msg,args);//正确用法是vprintf(msg,args);
    va_end(args);
    exit(1);

}

这种形式的应用不定参数有误,查资料良久才找到原来printf,fprintf及sprintf等函数都有专门的处理不定入参的函数

即在函数名前加v即vprintf,vfprintf及vsprintf;

当然这种办法是系统库本身提供了处理方法,当我们的函数不具有对应的方法是我们可以采用宏定义的方式完成上

述功能:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdarg.h>


#define err_quit(msg, args...) {printf(msg, ##args); exit(1);}

应用##符号将args表示的后续参数直接接在msg之后,函数正常执行,这个方法简单易懂,推荐使用,

对于vprintf等的具体实现,因为va_list实际是就是char *的字符串,应该是对字符串进行解析之后的结果。

最后来个gif图片轻松一下