开发手册 欢迎您!
软件开发者资料库

C语言函数可变参数

函数是仅在调用时运行的代码块。可以将数据(称为参数)传递给函数。函数可以返回数据。函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。函数能提高应用的模块性,和代码的重复利用率。本文主要介绍C语言中函数的可变参数。

1、可变参数

可变参数是指函数带有可变数量的参数,而不是预定义数量的参数。函数需要固定数量的强制参数(mandatory argument),后面是数量可变的可选参数(optional argument)。C语言中最常用的可变参数函数例子是 int printf(const char *format, ...)

参数列表的格式是强制性参数在前,后面跟着一个逗号和省略号(...),这个省略号代表可选参数。

例如,

#include // 函数add() 计算可选参数之和// 参数:第一个强制参数指定了可选参数的数量,可选参数为double类型// 返回值:和值,double类型double add( int n, ... ){  int i = 0;  double sum = 0.0;  va_list argptr;  va_start( argptr, n );             // 初始化argptr  for ( i = 0; i < n; ++i )       // 对每个可选参数,读取类型为double的参数,    sum += va_arg( argptr, double ); // 然后累加到sum中  va_end( argptr );  return sum;}int main (){   printf("多个数相同的结果是%f", add(6,3,4,6,7,8,9));   return(0);}

注意:函数 add() 最后一个参数写成省略号,即三个点号(...),省略号之前的那个参数是 int n,代表了要传递的可变参数的总数。为了使用这个功能,需要使用 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,type) ( *(type *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
#define va_end(ap) ( ap = (va_list)0 )

1)定义一个函数,最后一个参数为省略号,省略号前面可以设置自定义参数。

在函数定义中创建一个 va_list 类型变量,该类型是在 stdarg.h 头文件中定义的。

2)使用 int 参数和 va_start 宏来初始化 va_list 变量为一个参数列表。宏 va_start 是在 stdarg.h 头文件中定义的。

3)使用 va_arg 宏和 va_list 变量来访问参数列表中的每个元素。

4)使用宏 va_end 来清理va_list 变量的内存。

5)宏va_start通过该宏定义可以获取到可变参数表的首地址,并将该地址赋给指针ap

6)宏va_arg通过该宏定义可以获取当前ap所指向的可变参数,并将指针ap指向下一个可变参数。注意,该宏的第二个参数为类型。

7)宏va_end通过该宏定义可以结束可变参数的获取。

例如,

#include #include void myprintf(const char *format, ...){    va_list ap;    char c;    va_start(ap, format);    while (c = *format++) {        switch(c) {            case 'c': {                char ch = va_arg(ap, int);                putchar(ch);                break;            }            case 's': {                char *p = va_arg(ap, char *);                fputs(p, stdout);                break;            }            default:                putchar(c);        }    }    va_end(ap);}int main(void){    myprintf("c\ts\n", '1', "hello");    return 0;}