C語(yǔ)言的可變參數(shù)函數(shù)實(shí)現(xiàn)詳解
1、簡(jiǎn)介
今天看到一個(gè)有趣的東西C語(yǔ)言的可變參數(shù)函數(shù)
眾所周知,C語(yǔ)言的函數(shù)不能重載,那么你printf和scanf是怎么可以輸入多個(gè)參數(shù)的
例如查看到的printf的定義為
printf(const char *_Restrict, ...);
這稱為可變參數(shù)函數(shù)。這種函數(shù)需要固定數(shù)量的強(qiáng)制參數(shù),后面是數(shù)量可變的可選參數(shù)
這種函數(shù)必須至少有一個(gè)強(qiáng)制參數(shù)。可選參數(shù)的類型可以變化??蛇x參數(shù)的數(shù)量由強(qiáng)制參數(shù)的值決定,或由用來(lái)定義可選參數(shù)列表的特殊值決定。
C 語(yǔ)言中最常用的可變參數(shù)函數(shù)例子是 printf()和 scanf()。這兩個(gè)函數(shù)都有一個(gè)強(qiáng)制參數(shù),即格式化字符串。格式化字符串中的轉(zhuǎn)換修飾符決定了可選參數(shù)的數(shù)量和類型。
對(duì)于每一個(gè)強(qiáng)制參數(shù)來(lái)說(shuō),函數(shù)頭部都會(huì)顯示一個(gè)適當(dāng)?shù)膮?shù),像普通函數(shù)聲明一樣。參數(shù)列表的格式是強(qiáng)制性參數(shù)在前,后面跟著一個(gè)逗號(hào)和省略號(hào)(...),這個(gè)省略號(hào)代表可選參數(shù)。
可變參數(shù)函數(shù)要獲取可選參數(shù)時(shí),必須通過(guò)一個(gè)類型為 va_list 的對(duì)象,它包含了參數(shù)信息。這種類型的對(duì)象也稱為參數(shù)指針(argument pointer),它包含了棧中至少一個(gè)參數(shù)的位置??梢允褂眠@個(gè)參數(shù)指針從一個(gè)可選參數(shù)移動(dòng)到下一個(gè)可選參數(shù),由此,函數(shù)就可以獲取所有的可選參數(shù)。va_list 類型被定義在頭文件 stdarg.h 中。
void va_start(va_list argptr, lastparam);
宏 va_start 使用第一個(gè)可選參數(shù)的位置來(lái)初始化 argptr 參數(shù)指針。該宏的第二個(gè)參數(shù)必須是該函數(shù)最后一個(gè)有名稱參數(shù)的名稱。必須先調(diào)用該宏,才可以開始使用可選參數(shù)。
type va_arg(va_list argptr, type);
展開宏 va_arg 會(huì)得到當(dāng)前 argptr 所引用的可選參數(shù),也會(huì)將 argptr 移動(dòng)到列表中的下一個(gè)參數(shù)。宏 va_arg 的第二個(gè)參數(shù)是剛剛被讀入的參數(shù)的類型。
void va_end(va_list argptr);
當(dāng)不再需要使用參數(shù)指針時(shí),必須調(diào)用宏 va_end。如果想使用宏 va_start 或者宏 va_copy 來(lái)重新初始化一個(gè)之前用過(guò)的參數(shù)指針,也必須先調(diào)用宏 va_end。
void va_copy(va_list dest, va_list src);
宏 va_copy 使用當(dāng)前的 src 值來(lái)初始化參數(shù)指針 dest。然后就可以使用 dest 中的備份獲取可選參數(shù)列表,從 src 所引用的位置開始。
2、簡(jiǎn)單的使用方式
// 函數(shù)add() 計(jì)算可選參數(shù)之和 // 參數(shù):第一個(gè)強(qiáng)制參數(shù)指定了可選參數(shù)的數(shù)量,可選參數(shù)為double類型 // 返回值:和值,double類型 int add( int n, ... ) { int i = 0; int sum = 0.0; va_list argptr; va_start( argptr, n ); // 初始化argptr for ( i = 0; i < n; ++i ) // 對(duì)每個(gè)可選參數(shù),讀取類型為int的參數(shù), sum += va_arg( argptr, int ); // 然后累加到sum中 va_end( argptr ); return sum; } int main(int argc, char *argv[]) { int sum = add(5,1,2,3,4,5); printf("%d\n",sum); }
以上內(nèi)容均來(lái)自-
http://c.biancheng.net/view/344.html
總結(jié)
本篇文章就到這里了,希望能給你帶來(lái)幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
使用C++中的ADO對(duì)SQLite進(jìn)行增刪改查
本文將介紹如何使用C++的ADO (ActiveX Data Objects)對(duì)SQLite數(shù)據(jù)庫(kù)進(jìn)行增刪改查操作,文中有詳細(xì)的代碼示例,需要的朋友可以參考下2023-06-06用C語(yǔ)言模仿Python函數(shù)的一種簡(jiǎn)單實(shí)現(xiàn)方法
這篇文章主要介紹了用C語(yǔ)言模仿Python函數(shù)的一種簡(jiǎn)單實(shí)現(xiàn)方法,需要的朋友可以參考下2017-05-05c++基礎(chǔ)學(xué)習(xí)之如何區(qū)分引用和指針
C語(yǔ)言中只有指針,C++加入了引用,能夠起到跟指針類似的作用,下面這篇文章主要給大家介紹了關(guān)于c++基礎(chǔ)學(xué)習(xí)之區(qū)分引用和指針的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下2021-08-08C++課程設(shè)計(jì)之運(yùn)動(dòng)會(huì)管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了C++課程設(shè)計(jì)之運(yùn)動(dòng)會(huì)管理系統(tǒng),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-10-10C++模板以及實(shí)現(xiàn)vector實(shí)例詳解
模板是為了實(shí)現(xiàn)泛型編程,所謂泛型編程,就是指編寫與類型無(wú)關(guān)的代碼,下面這篇文章主要給大家介紹了關(guān)于C++模板以及實(shí)現(xiàn)vector的相關(guān)資料,需要的朋友可以參考下2021-11-11C++實(shí)現(xiàn)LeetCode(76.最小窗口子串)
這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(76.最小窗口子串),本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-07-07