int printf ( const char *format, ... ); |
從函數原型可以看出,其除了接收一個固定的參數format以外,後面的參數用"..."表示。在C/C++語言中,"…"表示可以接受不定數量的參數,理論上來講,可以是0或0以上的n個參數。
參數可以分爲兩部分:個數確定的固定參數和個數可變的可選參數。函數至少需要一個固定參數,固定參數的聲明和普通函數一樣;可選參數由於個數不確定,聲明時用"..."表示。固定參數和可選參數公同構成一個函數的參數列表。
標準C/C++包含頭文件stdarg.h,該頭文件中定義瞭如下三個宏:
void va_start ( va_list arg_ptr, prev_param ); /* ANSI version */ type va_arg ( va_list arg_ptr, type ); void va_end ( va_list arg_ptr ); |
在這些宏中,va就是variable argument(可變參數)的意思;
#define va_start ( ap, v ) ( ap = (va_list)&v + _INTSIZEOF(v) ) |
顯而易見,其含義爲將最後那個固定參數的地址加上可變參數對其的偏移後賦值給ap,這樣ap就是可變參數表的首地址。其中的_INTSIZEOF宏定義爲:
#define _INTSIZEOF(n) ((sizeof ( n ) + sizeof ( int ) - 1 ) & ~( sizeof( int ) - 1 ) ) |
va_start(arg_ptr, argN):使參數列表指針arg_ptr指向函數參數列表中的第一個可選參數,說明:argN是位於第一個可選參數之前的固定參數,(或者說,最後一個 固定參數;…之前的一個參數),函數參數列表中參數在內存中的順序與函數聲明時的順序是一致的。如果有一va函數的聲明是void va_test(char a, char b, char c, …),則它的固定參數依次是a,b,c,最後一個固定參數argN爲c,因此就是va_start(arg_ptr, c)。
#define va_arg(list, mode) ((mode *)(list = (char *) ((((int)list + (__builtin_alignof(mode)<=4?3:7)) & (__builtin_alignof(mode)<=4?-4:-8))+sizeof(mode))))[-1] |
va_end宏被用來結束可變參數的獲取,其定義爲:
#define va_end ( list ) |
可以看出,va_end ( list )實際上被定義爲空,沒有任何真實對應的代碼,用於代碼對稱,與va_start對應;
#include <stdarg.h> |