日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

变长参数

發布時間:2023/12/10 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 变长参数 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

轉載自:http://blog.csdn.net/tht2009/article/details/7019635

? ?變長參數

?設計一個參數個數可變、參數類型不定的函數是可能的,最常見的例子是printf函數、scanf函數和高級語言的Format函數。在C/C++中,為了通知編譯器函數的參數個數和類型可變(即是不定的、未知的),就必須以三個點結束該函數的聲明。

// printf函數的聲明int printf(const char * _Format, ...);//scanf函數聲明int scanf(const char * _Format, ...);//自定義變長參數函數func的聲明int func(int a,int b,...);

??????????上面func函數的聲明指出該函數至少有兩個整型參數和緊隨其后的0個或多個類型未知的參數。在C/C++中,任何使用變長參數聲明的函數都必須至少有一個指定的參數(又稱強制參數),即至少有一個參數的類型是已知的,而不能用三個點省略所有參數的指定,且已知的指定參數必須聲明在函數最左端。

int func(...);//錯誤 int func(...,int a);//錯誤

? ? ??變長參數函數的實現

?????? 含有變長參數的函數是怎么實現的呢?變長參數函數的實現其實關鍵在于怎么使用參數,指定了的參數好說,直接使用指定的參數名稱訪問,但未指定的參數呢?我們知道函數調用過程中參數傳遞是通過棧來實現的,一般調用都是從右至左的順序壓參數入棧,因此參數與參數之間是相鄰的,知道前一個參數的類型及地址,根據后一個參數的類型就可以獲取后一個參數的內容。對于變長參數函數,結合一定的條件,我們可以根據最后一個指定參數獲取之后的省略參數內容。如,對于函數func,我們知道了參數b的地址及類型,就可知道第一個可變參數的棧地址(如果有的話),如果知道第一個可變參數的類型,就可知道第一個可變參數的內容和第二個可變參數的地址(如果有的話)。以此類推,可以實現對可變參數函數的所有參數的訪問。

?????? 那么,要怎么指定上訴的“一定的條件”呢?最簡單的方法就像printf等函數一樣,使用格式化占位符。分析格式化字符串參數,通過事先定義好的格式化占位符可知可變參數的類型及個數,從而獲取各個參數內容。一般對于可變參數類型相同的函數也可直接在強制參數中指定可變參數的個數和類型,這樣也能獲取各個參數的內容。

?????? 無論哪種,都涉及對棧地址偏移的操作。結合棧存儲模式和系統數據類型的字長,我們可根據可變參數的類型很容易得到棧地址的偏移量。這里簡單介紹使用va_start、va_arg、va_end三個標準宏來實現棧地址的偏移及獲取可變參數內容。這三個宏定義在stdarg.h頭文件中,他們可根據預先定義的系統平臺自動獲取相應平臺上各個數據類型的偏移量。

va_list args; //定義一個可變參數列表 va_start(args,arg);//初始化args指向強制參數arg的下一個參數; va_arg(args,type);//獲取當前參數內容并將args指向下一個參數 ...//循環獲取所有可變參數內容 va_end(args);//釋放args

實現一個簡單的變長參數函數:

//sum為求和函數,其參數類型都為int,但參數個數不定 //第一個參數(強制參數)n指定后面有多少可變參數 int sum(unsigned int n,...) { int sum=0; va_list args; va_start(args,n); while(n>0) { //通過va_arg(args,int)依次獲取參數的值 sum+=va_arg(args,int); n--; } va_end(args); return sum; }


?????? 對于可變參數函數的調用有一點需要注意,實際的可變參數的個數必須比前面強制參數中指定的個數要多,或者不小于,也即后續參數多一點不要緊,但不能少,如果少了則會訪問到函數參數以外的堆棧區域,這可能會把程序搞崩掉。前面強制參數中指定的類型和后面實際參數的類型不匹配也有可能造成程序崩潰。?

?變長參數函數與默認參數函數

?

?????? 擁有變長參數的函數在聲明定義時其參數個數與類型是不定的,在運行調用時參數的狀態則是一定的。而默認參數函數在聲明定義時其參數類型與個數都是一定的,只是后面部分參數指定了默認值,可通過省略(不指定)部分參數調用這個默認參數函數。但是默認參數函數還是使用了聲明中指定的全部參數,只不過編譯器做了個順水人情,自動給后部分參數賦了默認值;而變長參數函數則僅僅使用了運行調用時提供的參數。

總結

以上是生活随笔為你收集整理的变长参数的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。