最經典的例子就是 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