亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C++ > 正文

C++可變參數的實現

2020-02-24 14:35:38
字體:
來源:轉載
供稿:網友

C++可變參數的實現,可變參數給編程帶來了很大的方便,在享受它帶來的方便的同時,很有必要了解一下其實現方式,在了解編程語言的同時,也可以擴展編程的思路。

可變參數的實現要解決三個問題:

1.如何調用帶有可變參數的函數
2.如何編譯有可變參數的程序
3.在帶有可變參數的函數體中如何持有可變參數
第一個問題, 調用時在可以傳入可變參數的地方傳入可變參數即可,當然,還有一些需要注意的地方,后面會提到。

第二個問題,編譯器需要在編譯時采用一種寬松的檢查方案,,這會帶來一些問題, 比如對編程查錯不利。

第三個是我在這里要關心的問題,先以C語言為例分析其實現原理。

printf和scanf是C語言標準庫中最常見的可變參數函數, printf的簽名是

?


int printf(const char* format, ...);

?

其中,... 表示可變參數,現在模仿printf寫一個簡單的例子。

一、一個簡單了例子:

?


#include
#include

?

void VariableArgumentMethod(int argc, ...);

int main(){
??? VariableArgumentMethod(6, 4, 7, 3, 0, 7, 9);
??? return 0;
}

void VariableArgumentMethod(int argc, ...){
??? // 聲明一個指針, 用于持有可變參數
??? va_list pArg;
??? // 將 pArg 初始化為指向第一個參數
??? va_start(pArg, argc);
??? // 輸出參數
  for(int i = 0; i != argc; ++i){
??????? // 獲取 pArg 所指向的參數并輸出
??????? printf("%d, ", va_arg(pArg, int) );
??? }

??? va_end(pArg);
}


void VariableArgumentMethod(int argc, ...)是一個可變參數函數,這個函數用于將 argc 指定個數的可變參數輸出。
VariableArgumentMethod(6, 4, 7, 3, 0, 7, 9); 是對這個函數的調用,第一個實參 6 表示后面跟了 6 個參數。

?

在 VariableArgumentMethod 的函數體中:

1. va_list pArg;

定義了一個用于持有可變參數的指針,通過將這個指針在傳入的可變參數表中移動,可以持有第一個可變參數。

2. va_start(pArg, argc);

讓 pArg 指向可變參數列表中的第一個參數。argc 是一個用來定位的參數,因為可變參數是從 argc 后開始的,后面會說明為什么要這樣定位。

3. va_arg(pArg, int);

這句話放在循環(huán)體中,用于取出可變參數表中的參數。并且,它會讓 pArg 移向下個可變參數(如果已經到達末尾,則它將指向一個沒有意義的地址)。

4. va_end(pArg);

給 pArg 清零,個人認為在這里可有可無,因為 pArg 已經不需要了。

?

就這樣,VariableArgumentMethod 函數體遍歷了可變參數表中傳入的參數,并用printf("%d, ", va_arg(pArg, int) ) 進行了輸出。

二、實現細節(jié)

1. 先了解一下編譯器如何處理傳遞參數這個問題的。

編譯器是將參數壓入棧中進行傳遞的。傳遞實參的時候,編譯器會從實參列表中,按從右到左的順序將參數入棧,對于 VariableArgumentMethod(6, 4, 7, 3, 0, 7, 9)調用,則入棧的順序是 9, 7, 0, 3, 7, 4, 6 (注意沒有可變參數與不可變參數之分)。由于棧的地址是從高到低的,所以實參入棧后,實參在棧中的分布如下圖??梢钥闯?,實參在棧中,還是保持了左邊參數處于低地址,右邊參數處于高地址的狀態(tài)。OK,知道這些就夠了。

低地址?                           高地址

?

...

6

4

7

3

0

7

9

...

?

2. va_list, va_start, va_arg 和 va_end

va_list 是一個定義的指針類型,va_start, va_arg 和 va_end 都是C語言用于處理可變參數而定義的宏,在stdarg.h文件中。由于硬件平臺的不同,編譯器的不同,導致它們的定義也有所不同,但基本思路相同。以下是相關宏的定義。

?


typedef char *? va_list;

?

#define _ADDRESSOF(v)?? ( &(v) )

#define _INTSIZEOF(n)?? ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )

#define va_start(ap,v)? ( ap = (va_list)_ADDRESSOF(v) + _INTSIZEOF(v) )

#define va_arg(ap,t)??? ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )

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

?

可以看出,此處引入了另外兩個宏 _ADDRESSOF 和 _INTSIZEOF。

_ADDRESSOF(v) 是用于獲取變量地址的,這一眼就能看出來;

_INTSIZEOF(n) 是用于對齊的。(什么是對齊呢?這是因為棧的結構導致的,在 32 位機中,棧中每個單元都是占 4 個字節(jié)的,這往往是一個 int 型的長度,但實際傳過來的參數可能并不正好是 4 個字節(jié),或者正好是 4 的倍數個字節(jié),就好像坐車時不會賣半個座位給乘客一樣,如果傳入的數據沒有正好占 4 個或 4 的倍數個字節(jié),則需要對齊(補齊)。至于為什么這個表達式能夠對齊,需要分析一下);

va_start(ap,v) 中,ap 是用于持有可變參數的指針, v 是最后一個非可變參數的參數,(va_list)_ADDRESSOF(v) 獲取 v 的地址,并轉為 va_list 類型的,v 是最后一個非可變參數的參數,在本例中應為 6, 在上圖中處理棧的低地址端,_INTSIZEOF(v) 獲取了一個對齊地址,這里應為 4, 兩個相加后,即指向了第一個可變參數,即上圖中的 4, 將這個值賦給 ap 后,就讓 ap 指向了第一個可變參數。(從這里可以看出,將va_list 定義為 char* 是很有用的,因為 char 長度為一個字節(jié),便于指針運算);

?va_arg(ap,t) 中,ap 是用于持有可變參數的指針,t 是要獲取參數的類型,ap += _INTSIZEOF(t) 讓 ap 指向下一個參數,但是,此處還需要獲取當前參數的值,所以又將表達式減回來,返回的應是一個 va_list(char*) 型的指針,因此要轉型為 t* 后再進行解引用運算,得到當前參數的值。(注意這里有個將 ap 移向下一個參數又減回來的操作,本人感覺不太好,一方面這里有個浪費的操作,對性能會有一些影響,另一方面,我更希望將取當前值的操作和移向下一個的操作分離,這樣可以讓程序員有更多的控制,并且容易理解。)

va_end(ap) 則是讓 ap 指向一個空地址。

通過以上分析,可以發(fā)現,C 語言中可變參數是從棧中按順序訪問的,過程中所使用的三個宏,也只是對操作的簡單包裝,完全可以自己編程實現。而且,參數的類型和個數是不能直接確定的,在本例中,VariableArgumentMethod 的第一個參數用于指定參數的個數,而參數的類型約定為整形,這樣程序才能正常運行,再說到 printf,它之所以能識別參數的個數,是因為它的第一個參數中必須要描述后面參數的格式字符串,這正是一開始所提到的第一個問題中說到的要注意的問題。這也是它被很多人所詬病的原因,但是,本人認為這種方式是很好的,后面會與 java 和 .net 的實現方式進行比較。

三、java 和 .net 實現可變參數的方式。

java 從1.5以后,開始支持可變參數,其定義語法為:

?


void testMethod(String ... args)


對于這個方法,可以這樣調用:testMethod("gly", "zxy", "ChenFei");

?

.net 也支持可變參數,其定義語法為:

?


void TestMethod(params string[] args)

?

對于這個方法,可以這樣調用:TestMethod("gly", "zxy", "ChenFei");

在 java 和 .net 中,對于可變參數的實現基本是一樣的:編譯器在編譯時,將方法簽名中的可變參數視為相應類型的數組,編譯相應的調用時,根據實參生成一個數組,將參數裝入到數組中進行傳遞,而在可變參數方法的方法體中,按使用數組的方式使用可變參數。

四、兩種實現方式的比較

C 語言的實現方式與 java .net 的實現方式相比,C 語言需要程序員做更多的工作,而且,確實增加了出錯的機會,java .net 的實現方式可以很容易的確定參數的類型和個數,這些 C 的實現中是沒有的,但是 java .net 的實現方式會生成臨時數組,當然 java .net 有垃圾回收機制,但是,垃圾什么時候被回收是不確定的,而且是代價很大的,垃圾回收是個好東西,但我不喜歡,我認為不需要的東西應該立即釋放,這是完美的一個方面的體現。C 中沒有這個問題,參數的個數和類型問題可以靠約定或指定來解決,而這兩個問題在 java 和 .net 中,參數個數其實是間接傳遞過去了(數組的長度),參數類型則是在方法簽名中約定了。當然,java .net 的設計目標和 C 語言不同,這里說多了。

?以上就是C++可變參數的實現,如果還有其他疑問,歡迎補充,有任何問題也可以與武林編輯一起討論。

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
国产三区在线观看| 鲁一鲁一鲁一鲁一色| 亚洲精品小视频在线观看| 欧美限制电影| 樱桃成人精品视频在线播放| 91精品婷婷国产综合久久竹菊| www.久久ai| 91精品久久久久久综合五月天| 亚洲狼人综合网| www.污视频| 激情五月色综合亚洲小说| 日韩大片在线观看| 中文字幕の友人北条麻妃| 国产免费成人| 久久九九精品| 免费成人黄色网| 日本精品影院| 91porny在线| 麻豆国产原创| 国产精品国产三级国产aⅴ9色| 成年人在线看| 成人午夜大片| 日韩欧美国产精品一区| 青春草在线视频| 国产黄色网页| 日韩在线一区二区三区免费视频| 久久精品1区| 亚洲一区导航| 国产激情在线观看| 成人国产精品久久| 亚洲精品鲁一鲁一区二区三区| 九九免费精品视频在线观看| 青青草免费在线视频| 国产va免费精品观看精品| 精品少妇一区二区三区在线视频| 污网站在线看| 网友自拍一区| 污污的网站18| 全部孕妇毛片丰满孕妇孕交| 久久国产精品免费一区| 性色av蜜臀av浪潮av老女人| julia京香一区二区三区| www夜片内射视频日韩精品成人| 中文字幕亚洲在线| 九九热在线观看视频| 免费啪视频在线观看| 欧美大片在线播放| 91精品久久久久久蜜桃| 国产一级特黄a大片免费| 欧美成人milf| bt欧美亚洲午夜电影天堂| 无码aⅴ精品一区二区三区| 国产l精品国产亚洲区久久| 久久亚洲免费视频| jvid一区二区三区| 久久久久99精品成人片毛片| www亚洲成人| 国产成人精品实拍在线| 国产日韩高清一区二区三区在线| 精品va天堂亚洲国产| 日韩av二区| 欧美多人猛交狂配| 六月婷婷七月丁香| 欧美成人精品福利网站| 日韩中文字幕免费观看| 男人添女荫道口喷水视频| 国产95在线|亚洲| 日本爱爱免费视频| 欧美香蕉视频| 91国拍精品国产粉嫩亚洲一区| 成人小说亚洲一区二区三区| 久无码久无码av无码| 久热久精久品这里在线观看| 农村妇女精品一区二区| 亚洲经典中文字幕| 日韩欧美中文字幕电影| 国产免费一区二区三区在线观看| 日韩人妻无码一区二区三区| www.黄色网址| 欧美牲交a欧美牲交aⅴ免费下载| 欧美性感美女h网站在线观看免费| 国产真人无码作爱视频免费| 国语对白做受xxxxx在线中国| 久久久久久青草| 首页亚洲欧美制服丝腿| 怡红院一区二区| 久久精品水蜜桃av综合天堂| 麻豆视频在线观看免费| 亚洲网站在线免费观看| 黄在线观看网站| 97影院在线午夜| 欧美少妇在线观看| 动漫一区在线| 99re成人精品视频| 麻豆蜜桃在线| 亚洲另类在线视频| 日本在线免费观看一区| 国产精品熟女久久久久久| 欧美激情一区二区三区高清视频| 中文字幕一区三区| 91国内在线| 日韩国产一区| 羞羞视频立即看| 老司机精品导航| 欧美视频第一| 欧美一级欧美三级在线| 亚洲第一激情av| 一本岛在免费一二三区| 国产一区二区三区电影在线观看| 黄色视屏网站在线免费观看| 欧美日韩国产精品专区| 国产伦理一区二区| 欧洲美女精品免费观看视频| 亚洲三级黄色在线观看| 91蝌蚪国产九色| 成人开心激情| 992kp快乐看片永久免费网址| 天堂中文字幕——hd| 国产视频欧美| 99视频国产精品免费观看a| 黄网视频在线观看| 亚洲精品99999| www.综合色| 国产精品女人毛片| 日本午夜精品理论片a级app发布| 黄色裸体一级片| 亚洲欧洲美洲av| 成人免费看黄网站| 成人免费电影网址| 欧洲在线视频| 久久精品—区二区三区舞蹈| 3d性欧美动漫精品xxxx软件| 99热在线观看| 亚洲天堂av资源在线观看| 69久久夜色精品国产69蝌蚪网| 刘玥91精选国产在线观看| 亚洲视频观看| 欧美理论视频| 欧美国产高潮xxxx1819| 国产馆av播放| 久久精品123| 亚洲色图欧美视频| av官网在线| 三级欧美在线一区| 综合分类小说区另类春色亚洲小说欧美| 国产区视频在线观看| 特黄毛片在线观看| 久久伊伊香蕉| 五月婷婷六月色| 精品福利免费观看| 色8久久影院午夜场| 给我看免费高清在线观看| 国产高清自拍视频在线观看| 国产精品久久久高清免费| 国产福利在线播放麻豆| 成人免费视频视频在线观看免费| 一本大道久久a久久综合婷婷| 欧美虐宫另类残忍视频| xxxx性欧美| 久久久久久www| 欧美性xxxxx极品视频| 国产日产欧美精品一区二区三区| 欧美一级片网址| 欧美经典三级视频一区二区三区| 国产精品天干天干在线综合| 色橹橹欧美在线观看视频高清| 国模吧精品人体gogo| 成人午夜又粗又硬又大| 永久免费网站在线| 国产精品suv一区二区69| 国产精品视频免费在线| 欧美特黄不卡| 久久国产一级片| 中文字幕手机在线观看| www.男人天堂网| 亚洲美女搞黄| 欧美一区午夜精品| 24小时免费看片在线观看| 午夜在线一区二区| 一级毛片在线视频| h七七www色午夜日本| 久久国产精品国语对白| 久久久国产精华液| 国产欧美综合一区| 99爱在线观看| 久久久久久久一| 精品乱码一区| 91丨九色丨尤物| 国产精品成人一区二区网站软件| 4p变态网欧美系列| 国产成人精品123区免费视频| а√天堂中文在线资源bt在线| 国产午夜精品一区二区三区欧美| 最全影音av资源中文字幕在线| 午夜剧场成人观在线视频免费观看| 国产寡妇亲子伦一区二区| 91久久精品无码一区二区| 日韩精品亚洲aⅴ在线影院| 欧美日韩在线免费播放| 亚洲免费资源| 日韩a级作爱片一二三区免费观看| 中文字幕中文字幕在线中一区高清| 无码国产精品一区二区色情男同| 日韩电影一区二区三区| 日本成人在线视频网址| 牛人国产偷窥女洗浴在线观看| 亚洲精品自在久久| 中文在线免费二区三区| 激情婷婷综合网| 欧美三级韩国三级日本三斤| 竹内纱里奈兽皇系列在线观看| 欧美日韩夫妻久久| 亚洲精品永久视频| 国产色综合一区二区三区| 成年人午夜久久久| 成人精品天堂一区二区三区| 久草福利视频在线| 在线观看视频你懂得| 91精品久久久久久粉嫩| 日韩人妻一区二区三区| 日韩欧美一级二级三级| 成人免费视频网站在线观看| 欧美亚洲另类激情另类| 91麻豆精品秘密| 高清中文字幕一区二区三区| 国产精品高清无码在线观看| 亚洲天堂中文在线| 麻豆视频入口| 日韩午夜av| 亚洲精品乱码久久久久久蜜桃91| 日本免费一区二区六区| 91亚洲精品一区二区| 日韩一区二区三区在线播放| 国产精品一二三在线观看| 麻豆视频在线| 亚洲成av人影片在线观看| 九九热视频在线观看| 欧美大片91| 色av一区二区三区| 亚洲成人一区在线观看| xxxx性bbbb欧美野外| 动漫美女无遮挡免费| 杨幂一区二区国产精品| 波多野结衣中文字幕在线| 国产成人精品久久一区二区小说| 欧美黑人疯狂性受xxxxx野外| 日本v片在线免费观看| 免费看成人午夜电影| 亚洲第一页中文字幕| 欧美群妇大交群的观看方式| 久热国产视频| 久久久久久久久久久久久久av| 蜜桃精品在线| 天堂在线视频网站| 日本中文字幕有码| 国产成人在线视频观看| 日本精品久久中文字幕佐佐木| 精品福利一区二区三区免费视频| 欧美一级片中文字幕| 欧美最新精品| 欧美在线中文| 蘑菇福利视频一区播放| 免费高清在线观看| 国产一区免费视频| 黄网址在线播放免费| 精品久久久久久亚洲综合网| 91成人破解版| 亚洲精品视频网址| 玖玖爱在线精品视频| 国产激情偷乱视频一区二区三区| 91首页免费视频| 成人免费看黄yyy456| 日韩不卡视频在线| 日韩在线视频免费观看高清中文| 久久精品欧美日韩| av在线不卡免费看| 久久久国产免费| 亚洲精品国精品久久99热一| 日韩欧美一级二级三级| 激情91久久| 欧美视频导航| 亚洲 国产 欧美 日韩| 成人午夜av影视| 99在线观看免费视频精品观看| 91影院在线播放| 国产久卡久卡久卡久卡视频精品| www.污网站| 亚洲专区欧美专区| 黄色在线免费观看| 中文字幕+乱码+中文乱码91| 国产一区二区高清不卡| 最新91视频| www.av在线播放| 国产在线一区二区视频| 99精品在线观看视频| 一区二区在线免费观看| 中国一区二区三区| 免费看男男www网站入口在线| av中文在线观看| 国产精品久久久久久久久搜平片| 久久久久久久久久久免费精品| 日韩少妇中文字幕| 日韩欧美中文字幕在线观看| 鲁大师精品99久久久| 国产精品中文字幕在线观看| 国产精品边吃奶边做爽| 欧美最猛性xxxxxhd| 午夜免费一区二区| 精品国产成人av在线免| 成人激情视频| 精品无人区一区二区三区| 日韩在线无毛| 国内精品一区二区三区四区| 在线观看成人毛片| 中文字幕福利视频| 欧美三级黄视频| 色视频免费在线观看| 国产亚洲精品久久777777| 天天操天天插天天射| 中国精品一区二区| 深夜福利影院在线观看| 欧美视频一区二区| 国内精品一区二区三区四区| 欧美.日韩.国产.一区.二区| 精品亚洲国产成人av制服丝袜| 欧美在线观看你懂的| 亚洲mm色国产网站| 成人性爱视频在线观看|