c的可變引數(va_arg,va_list,va_start,va_end)
阿新 • • 發佈:2020-11-25
首先是標頭檔案. <stdarg.h>
其次, 我們的目的是實現支援變長引數的函式, 但並不是說,這個函式引數可以全都是變的. 不行. 函式的引數列表中, 一定至少要有一個有name的引數. 比如printf, 它的定義是printf(const char * restrict format, ...);
也是有restrict format這個有name的引數的. 變參正如printf顯示的那樣, 是...
好了, 怎麼用呢. 我們拿一個網上部落格的例子. 出處是深入C語言可變引數(va_arg,va_list,va_start,va_end)
#include <stdio.h> #include <stdarg.h> void print_args(int count, ...); int main(int argc, char* argv[]) { print_args(5,1,2,3,4,5); return 0; } void print_args(int count, ...) { int i, value; va_list arg_ptr; va_start(arg_ptr, count); for(i=0; i<count; i++) { value = va_arg(arg_ptr,int); printf("position %d = %d\n", i+1, value); } va_end(arg_ptr); }
首先看函式的定義, 有一個有name的引數count, 除此之外就是變參...
要獲得變參, 首先需要定義一個va_list型別的變數, 這裡是va_list arg_ptr;
. 這個型別的變數, 之後會遍歷獲取到所有的引數, 這個變數我們會一直用, 一直到引數解析完畢.
但這個變數使用前必須初始化, 我們看到是va_start(arg_ptr, count);
, 這個函式實際上是一個巨集. 它需要兩個引數, 第一個是va_list型別的遍歷變數, 第二個引數是這個函式最後一個有name的引數, 這裡就是count. 但是va_start的作用是什麼呢?
The macro va_start initializes ap to point to the first unnamed argument.
讓它指向第一個unnamed的引數.
好了, 那麼怎麼獲得變參呢? 這就是value = va_arg(arg_ptr,int);
, 第一個引數自然是va_list
型別, 第二個引數是指定型別, 這樣才知道它佔的記憶體大小, 才知道它佔了多少, 下一步該到記憶體什麼位置. 返回就會返回int型別的. 這個va_arg
應該也是巨集.
最後必須在函式返回前呼叫va_end, K&R是這麼說的:
Finally, va_end does whatever cleanup is necessary.
好了再總結使用要點:
- 標頭檔案是<stdarg.h>
- 先定義va_list變數, 然後va_start它, 第二個引數是最後一個named引數
- va_arg(va_list變數, 型別)解析引數, 返回就是我們呼叫的引數.
- 最後用va_end釋放va_list變數.