首頁>技術>

可變引數列表:

在我們一般經常使用的函式中,函式列出了期望接受的引數,但函式原型只能顯示固定的引數,那麼,如何讓一個函式在不同的時候接受不同數目的引數呢!使用可變引數列表就可實現,當一個函式事先不確定有多少個引數但是可以接受一個或多個引數,可以使得函式可以接受1個以上的任意多個引數。

可變引數列表是透過宏來實現的,這些宏定義在stdarg.h標頭檔案中,在這個標頭檔案中聲明瞭 一個型別va_list和三個宏va_start、va_arg、va_end配合使用,訪問引數的值。

可變引數函式的原型宣告格式為:type VAFunction(type arg1, type arg2, … ); 引數可以分為兩部分:個數確定的固定引數和個數可變的可選引數。函式至少需要一個固定引數,固定引數的宣告和普通函式一樣;可選引數由於個數不確定,宣告時用"…"表示。固定引數和可選引數共同構成一個函式的引數列表。

舉個例子理解:比方求指定個數的平均值

#include <stdio.h>#include <stdarg.h>int average(int n,...) //定義一個函式,實現可變引數{	va_list arg;        //定義一個變數arg為va_list型別	int i = 0;	int sum = 0;	va_start(arg, n);    	for(i=0; i<n; i++)    //迴圈獲取引數	{		sum += va_arg(arg, int); 	}	return sum/n;	va_end(arg);               }int main(){	int ret1 = 0;	int ret2 = 0;	ret1 = average(3, 1,2,3);	ret2 = average(4, 2,3,3,5);	printf("%d\n",ret1);	printf("%d\n",ret2);	return 0;}

程式結果

在vs中我們可以轉到定義處檢視各個型別和宏具體是怎樣實現的

1、首先va_list arg;

#elif   defined(_M_IX86)#define _INTSIZEOF(n)   ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )#define _crt_va_start(ap,v)  ( ap = (va_list)_ADDRESSOF(v) + _INTSIZEOF(v) )#define _crt_va_arg(ap,t)    ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )#define _crt_va_end(ap)      ( ap = (va_list)0 )#elif defined(_M_IA64)

很明顯va_list就是一個型別重新命名;va_list實際上就是char*型,簡言之va_list arg就是聲明瞭一個字元型指標arg。

2、va_start(arg, n);

#elif   defined(_M_IX86)#define _INTSIZEOF(n)   ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )#define _crt_va_start(ap,v)  ( ap = (va_list)_ADDRESSOF(v) + _INTSIZEOF(v) )#define _crt_va_arg(ap,t)    ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )#define _crt_va_end(ap)      ( ap = (va_list)0 )#elif defined(_M_IA64)

_INTSIZEOF(n)整個做的事情就是將n的長度化為int長度的整數倍va_srart(ap,v)就是把上面的字元指標向後移動,跳過第一個引數n的地址。

3、va_arg(args, int)

#define _crt_va_end(ap)      ( ap = (va_list)0 )

va_arg(args, int) 就是迴圈獲取到可變引數列表中的引數,args指向下一個引數地址,返回的則是當前引數地址。4、va_end(arg);

#define _crt_va_end(ap)      ( ap = (va_list)0 )

當訪問完畢最後一個引數時,用VA_END宏結束可變引數的獲取。

可變引數列表的缺陷:

1、可變引數必須從頭到尾逐個訪問。如果你在訪問了幾個可變引數之後想半途終止,這是可以的,但是,如果你想一開始就訪問引數列表中間的引數,那是不行的

2、引數列表中至少有一個命名引數。如果連一個命名引數都沒有,就無法使用va_start。

3、如果在va_arg中指定了錯誤的型別,結果無法預測,因為在使用時,char、short、float型別的值實際上都作為int或double型別的值傳遞給函式。

10
最新評論
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • 15個使用頻率很低的SkLearn模型