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

1、可变参数

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

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

例如,

#include <stdio.h>
// 函数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 <stdio.h>
#include <stdarg.h>
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;
}

推荐文档