stdarg.h

stdarg 提供了可变长参数功能.

类型

va_list

一个可变长的参数列表.

va_start(ap, param)

初始化 va_list 参数列表. 可变长参数必须初始化后使用.

参数:
  • ap – 需要初始化的 va_list 变量.
  • param – 最后一个固定参数.
va_arg(ap, type)

从可变长参数列表 ap 中获取下一个 type 类型的参数.

如果 ap 中有不同类型的参数, 且 type 未改变, 则对应位置的参数会被跳过, 并且可能访问越界.

参数:
  • ap – 可变长参数列表.
  • type – 下一个获取的参数值的类型.
va_end(ap)

释放参数列表 ap 占用的内存.

va_copy(dest, src)

将 src 复制到 dest 当中. src 的读取状态也会被复制. dest 将无法获取已经被 src 提取过的参数.

参数:

示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
#include <stdarg.h>
#include <stdio.h>

/**
 * 虽然第一个参数 count 并不要求为可变参数的数目,
 * 但是读取可变参数的过程中需要这一个参数用于循环.
 *
 * 可以使用多个固定参数, 用省略号 ``...`` 表示接下来的参数数目不定.
 */
int sum(const int count, ...)
{
    va_list args;
    int sum = 0;
    int tmp;
    // 初始化参数列表, 传入第二个参数表示
    // 这个函数的最后一个固定参数.
    va_start(args, count);
    for (int i = 0; i < count; i++){
        // 从参数列表中获取下一个 int 类型的值
        tmp = va_arg(args, int);
        printf("%d, ", tmp);
        sum += tmp;
    }
    va_end(args);
    return sum;
}

double avg(int count, ...)
{
    va_list args, copied;
    double result = 0;
    double result_bak = 0;
    double tmp;
    va_start(args, count);
    // 先用掉一个
    result += va_arg(args, double);
    printf("%lf used, ", result);

    // 复制
    va_copy(copied, args);

    for(double i = 1; i < count; i++){
        tmp = va_arg(args, double);
        printf("%lf, ", tmp);
        result += tmp;
    }
    va_end(args);
    putchar('\n');
    for(double i = 0; i < count; i++){
        tmp = va_arg(copied, double);
        printf("%lf, ", tmp);
        result_bak += tmp;
    }
    va_end(copied);
    putchar('\n');

    return result / count;
}

int main(int argc, char *argv[])
{
    int result;
    // 由于 100.0 处被跳过, 最后访问越界
    result = sum(12, 1, 2, 3, 4, 5, 6, 7, 8, 100.0, 10, 11, 12);
    printf("\n%d\n", result);
    // 正确使用方法
    result = sum(3, 888, 999, 1000);
    printf("\n%d\n", result);

    avg(6, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0);
    return 0;
}