Variable Length Argument List in C

最經典的例子就是 printf()

1
int printf(char* fmt, ...)

後面的 ... 表示 variable length argument list,必須放在最後面。function 要用 variable length argument list 至少要有一個有名稱的參數,而且可以從這個參數中得知 variable length argument list 總共有多少參數。

在 function 裡處理 variable length argument list 主要要做的是從沒有對應名稱的 list 中取得內容,也就是要拿到參數們。標準函式庫的 stdarg.h 提供一組 macro 來做這件事,Ref

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
#include <stdio.h>
#include <stdarg.h>

void myfunc(char* fmt, ...)
{
va_list ap;
char* p = NULL;
va_start(ap, fmt);
for (p = fmt; *p; p++)
{
if (*p != '%')
{
putchar(*p);
continue;
}

++p; // %
switch (*p)
{
case 'd':
{
int val = va_arg(ap, int);
printf("%d", val);
break;
}
case 'f':
{
double val = va_arg(ap, double);
printf("%f", val);
break;
}
case 's':
{
for (char* val = va_arg(ap, char*); val && *val; ++val)
{
putchar(*val);
}
break;
}
default:
putchar(*p);
break;
}
}
va_end(ap);
}

int main()
{
int n = 123;
double f = 330.732;
char str[] = "KEKEKE";
myfunc("haha, test format: %d, %f, %s\n", n, f, str);
return 0;
}

至於 stdarg.h 裡怎麼定義 macro 的呢?

在 Ubuntu 底下追到 /usr/lib/gcc/x86_64-linux-gnu/5/include/stdarg.h 裡的:

1
2
3
#define va_start(v,l)   __builtin_va_start(v,l)
#define va_end(v) __builtin_va_end(v)
#define va_arg(v,l) __builtin_va_arg(v,l)

之後就不知道去哪了,似乎要到 GCC 的 source code 裡去看跟 builtin 有關的東西才找得到了。Ref