C语言可变参数的使用

可变参数函数指的是函数参数个数不固定的函数,类似printf(char* fmt, …);
如果想自己写一个可变参数的函数,需要用到stdarg.h头文件中的如下几个宏

void va_start( va_list arg_ptr, prev_param ); 
type va_arg( va_list arg_ptr, type ); 
void va_end( va_list arg_ptr );

-用法example.c

#include <stdio.h>
#include <stdarg.h>
void myprint(char* fmt, ...)
{
        va_list ap;
        int d;
        char ch, *str;
        va_start(ap,fmt);
        while(*fmt)
        {
                switch(*fmt++)
                {
                case 'd':
                        d=va_arg(ap, int);
                        printf("int %d\n", d);
                        break;
                case 's':
                        str = va_arg(ap, char *);
                        printf("string %s\n", str);
                        break;
                case 'c':
                        ch = (char)va_arg(ap, int);
                        printf("char %c\n", ch);
                        break;
                }
        }
        va_end(ap);
}

int main()
{
    myprint("%d,%s,%d,%s,%c",11,"str1",12,"str2",'@');  
    return 0;
}

运行结果:

int 11
string str1
int 12
string str2
char @

程序详解
1.首先定义可变参数函数时参数列表中使用(…)代表参数个数不确定,但是一定至少要有一个固定的参数,这里用 的是(char * fmt).
2. 定义va_list ap用来访问未列出的参数
va_list 、va_start、va_arg、va_end的定义如下

typedef char* va_list
#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 )

va_list ap定义的ap是一个指针。

va_start(ap,fmt) 将ap初始化赋值,指向第一个未列出的参数。
va_arg 每次返回一个参数的值,并且将ap后移至下一个参数地址
这个结合栈来看会更清晰,C语言的函数是从右至左入栈的,

 高地址|-----------------------------| 
|函数返回地址 | 
|-----------------------------| 
|....... | 
|-----------------------------| 
|第n个参数(第一个可变参数) | 
|-----------------------------|<--va_start后ap指向 
|第n-1个参数(最后一个固定参数)| 
|-----------------------------|<-- &fmt
低地址|-----------------------------|

va_end(ap) 将ap赋值为0,不指向任何地方。

注意:
ch = (char)va_arg(ap, int);
不能使用 ch=(char)va_arg(ap, char);
va_arg(argp, type)宏中不支持的type:
— char、signed char、unsigned char
— short、unsigned short
— signed short、short int、signed short int、unsigned short int
— float
float 用double代替,其他的用 int代替,char* 是可以用的。

参考
[http://blog.csdn.net/weiwangchao_/article/details/4857567]
[http://pcedu.pconline.com.cn/empolder/gj/c/0507/669879_1.html]

猜你喜欢

转载自blog.csdn.net/mynameislu/article/details/43985115