在函式的原型中,列出了函式期望接受的引數,但函式只能顯示固定數目的引數,讓乙個函式在不同的時候接受不同的數目引數是不是可以呢?答案是肯定的,但存在一些限制.
stdarg巨集
可變引數列表是通過巨集來實現的,這些巨集定義於stdarg.h標頭檔案中,它是標準庫的一部分.這個標頭檔案宣告乙個型別va_list,三個巨集va_start,va_arg,和va_end
接下來分析它們的作用和原理
typedef
char * va_list
va_list=char*
(va_list ap)
開始需宣告乙個va_list型別的指標ap,它用於訪問引數列表的未知部分
#define va_start(ap,v) (ap=(va_list)&v+_intsizeof(v))
其中v表示距離未知引數列表最近的確定引數.
(va_list)&v 取出v的位址,強轉成於ap同一型別
ap=(va_list)&v+_intsizeof(v) 讓ap指向未知引數列表中的第乙個引數
#define _intsizeof(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )
_intsizeof(v):將v的位元組數進行整形提公升,當v的位元組數為1,2,3,4則表示4個位元組,
當位元組數為9,10,11,12則表示為12個位元組依此類推
整個巨集的意義在於對ap進行初始化,使得ap指向引數列表第乙個引數
#define va_arg(ap,t) ( *(t *)((ap += _intsizeof(t)) - _intsizeof(t)) )
其中i為引數型別
逐步分析
(ap += _intsizeof(t):使得ap指向第二個引數
((ap += _intsizeof(t)) - _intsizeof(t))將整個表示式的指向第乙個引數
(t *)((ap += _intsizeof(t)) - _intsizeof(t))將表示式指標型別強制轉換成引數型別
(t )((ap += _intsizeof(t)) - _intsizeof(t)) 對整個表示式解引用,表示第乙個引數
此時巨集表示第乙個引數,而ap指向第二個引數,再次進行巨集替換時,巨集又表示第二個引數,十分巧妙.
#define va_end(ap) ( ap = (va_list)0 )
結束前,將ap賦值空.
可變引數的限制
注意,可變引數必須從頭到尾逐個訪問.可半途終止,但不可從任意位置開始訪問.
1.引數列表至少有乙個命名引數(確定引數),才能使用va_start給指標ap初始化(定位)
2.這些巨集是無法直接判斷實際存在引數的數量的.
3.這些巨集無法判斷每個引數的型別
4如果在va_arg中指定了錯誤的型別,那麼後果是不可**的
可變引數函式
c函式要在程式中用到以下這些巨集 void va start va list arg ptr,prev param type va arg va list arg ptr,type void va end va list arg ptr va list 用來儲存巨集va start va arg和v...
可變引數函式
一 什麼是可變引數 我們在c語言程式設計中有時會遇到一些引數個數可變的函式,例如printf 函式,其函式原型為 int printf const char format,它除了有乙個引數format固定以外,後面跟的引數的個數和型別是可變的 用三個點 做引數佔位符 實際呼叫時可以有以下的形式 pr...
可變引數函式
stdarg.h是 c語言中c標準函式庫的 標頭檔案,stdarg是由standard 標準 arguments 引數 簡化而來,主要目的為讓函式能夠接收可變引數。stdarg.h 資料型別 型別名稱 描述 va list 用來儲存巨集va arg與巨集va end所需資訊 巨集名稱 描述va st...