精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

淺談C/C++中可變參數(shù)的原理

開發(fā) 后端
以前只是知道C/C++可變參數(shù)怎么用,但是一直對它的原理是似懂非懂,現(xiàn)在對計(jì)算機(jī)有了比較深刻的認(rèn)識之后,回頭再看,豁然開朗。

要理解可變參數(shù),首先要理解函數(shù)調(diào)用約定, 為什么只有__cdecl的調(diào)用約定支持可變參數(shù),而__stdcall就不支持?

實(shí)際上__cdecl和__stdcall函數(shù)參數(shù)都是從右到左入棧,它們的區(qū)別在于由誰來清棧,__cdecl由外部調(diào)用函數(shù)清棧,而__stdcall由被調(diào)用函數(shù)本身清棧, 顯然對于可變參數(shù)的函數(shù),函數(shù)本身沒法知道外部函數(shù)調(diào)用它時(shí)傳了多少參數(shù),所以沒法支持被調(diào)用函數(shù)本身清棧(__stdcall), 所以可變參數(shù)只能用__cdecll.

另外還要理解函數(shù)參數(shù)傳遞過程中堆棧是如何生長和變化的,從堆棧低地址到高地址,依次存儲 被調(diào)用函數(shù)局部變量,上一函數(shù)堆棧楨基址,函數(shù)返回地址,參數(shù)1, 參數(shù)2, 參數(shù)3...,相關(guān)知識可以參考我的這篇堆棧楨的生成原理 

有了上面的知識,我可以知道函數(shù)調(diào)用時(shí),參數(shù)2的地址就是參數(shù)1的地址加上參數(shù)1的長度,而參數(shù)3的地址是參數(shù)2的地址加上參數(shù)2的長度,以此類推。

于是我們可以自己寫可變參數(shù)的函數(shù)了, 代碼如下:

  1. int Sum(int nCount, ) 
  2.     int nSum = 0; 
  3.     int* p = &nCount; 
  4.     for(int i=0; i<nCount; ++i) 
  5.     { 
  6.         cout << *(++p) << endl; 
  7.         nSum += *p; 
  8.     } 
  9.  
  10.     cout << "Sum:" << nSum << endl << endl; 
  11.     return nSum; 
  12.  
  13. string  SumStr(int nCount, ) 
  14.     string str; 
  15.     int* p = &nCount; 
  16.  
  17.     for(int i=0; i<nCount; ++i) 
  18.     { 
  19.         char* pTemp = (char*)*(++p); 
  20.         cout <<  pTemp << endl; 
  21.         str += pTemp; 
  22.     } 
  23.  
  24.     cout << "SumStr:" << str << endl; 
  25.     return str; 

在我們的測試函數(shù)中nCount表示后面可變參數(shù)的個(gè)數(shù),int Sum(int nCount, [[94242]])會打印后面的可變參數(shù)Int值,并且進(jìn)行累加;string  SumStr(int nCount, [[94242]]) 會打印后面可變參數(shù)字符串內(nèi)容,并連接所有字符串。

然后用下面代碼進(jìn)行測試:int main() 

  1.     Sum(3, 10, 20, 30); 
  2.     SumStr(5, "aa""bb""cc""dd""ff"); 
  3.      
  4.     system("pause"); 
  5.  
  6.     return 0; 

測試結(jié)果如下:

可以看到,我們上面的實(shí)現(xiàn)有硬編碼的味道,也有沒有做字節(jié)對齊,為此系統(tǒng)專門給我們封裝了一些支持可變參數(shù)的宏:

  1. //typedef char *  va_list; 
  2. //#define _ADDRESSOF(v)   ( &reinterpret_cast<const char &>(v) ) 
  3. //#define _INTSIZEOF(n)   ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) ) 
  4. //#define _crt_va_start(ap,v)  ( ap = (va_list)_ADDRESSOF(v) + _INTSIZEOF(v) ) 
  5. //#define _crt_va_arg(ap,t)    ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) ) 
  6. //#define _crt_va_end(ap)      ( ap = (va_list)0 ) 
  7. //#define va_start _crt_va_start 
  8. //#define va_arg _crt_va_arg 
  9. //#define va_end _crt_va_end 
  10. //#define _ADDRESSOF(v)   ( &reinterpret_cast<const char &>(v) ) 
  11. //#define _INTSIZEOF(n)   ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) ) 
  12. //#define _crt_va_start(ap,v)  ( ap = (va_list)_ADDRESSOF(v) + _INTSIZEOF(v) ) 
  13. //#define _crt_va_arg(ap,t)    ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) ) 
  14. //#define _crt_va_end(ap)      ( ap = (va_list)0 ) 
  15. //#define va_start _crt_va_start 
  16. //#define va_arg _crt_va_arg 
  17. //#define va_end _crt_va_end 

用系統(tǒng)的這些宏,我們的代碼可以這樣寫了:

  1. //use va_arg, praram is int 
  2. int SumNew(int nCount, ) 
  3.     int nSum = 0; 
  4.     va_list vl = 0; 
  5.     va_start(vl, nCount); 
  6.  
  7.     for(int i=0; i<nCount; ++i) 
  8.     { 
  9.         int n = va_arg(vl, int); 
  10.         cout << n << endl; 
  11.         nSum += n; 
  12.     } 
  13.  
  14.     va_end(vl); 
  15.     cout << "SumNew:" << nSum << endl << endl; 
  16.     return nSum; 
  17.  
  18. //use va_arg,  praram is char* 
  19. string SumStrNew(int nCount, ) 
  20.     string str; 
  21.     va_list vl = 0; 
  22.     va_start(vl, nCount); 
  23.  
  24.     for(int i=0; i<nCount; ++i) 
  25.     { 
  26.         char* p = va_arg(vl, char*); 
  27.         cout <<  p << endl; 
  28.         str += p; 
  29.     } 
  30.  
  31.     cout << "SumStrNew:" << str << endl << endl; 
  32.     return str; 

可以看到,其中 va_list實(shí)際上只是一個(gè)參數(shù)指針,va_start根據(jù)你提供的最后一個(gè)固定參數(shù)來獲取第一個(gè)可變參數(shù)的地址,va_arg將指針指向下一個(gè)可變參數(shù)然后返回當(dāng)前值, va_end只是簡單的將指針清0.

用下面的代碼進(jìn)行測試:

  1. int main()  
  2.     Sum(3, 10, 20, 30); 
  3.     SumStr(5, "aa", "bb", "cc", "dd", "ff"); 
  4.      
  5.     SumNew(3, 1, 2, 3); 
  6.     SumStrNew(3, "12", "34", "56"); 
  7.  
  8.     system("pause"); 
  9.  
  10.     return 0; 

結(jié)果如下: 

我們上面的例子傳的可變參數(shù)都是4字節(jié)的, 如果我們的可變參數(shù)傳的是一個(gè)結(jié)構(gòu)體,結(jié)果會怎么樣呢?

下面的例子我們傳的可變參數(shù)是std::string

  1. //use va_arg,  praram is std::string 
  2. void SumStdString(int nCount, ) 
  3.     string str; 
  4.     va_list vl = 0; 
  5.     va_start(vl, nCount); 
  6.  
  7.     for(int i=0; i<nCount; ++i) 
  8.     { 
  9.         string p = va_arg(vl, string); 
  10.         cout <<  p << endl; 
  11.         str += p; 
  12.     } 
  13.  
  14.     cout << "SumStdString:" << str << endl << endl; 
  15. int main()  
  16. Sum(3, 10, 20, 30); 
  17. SumStr(5, "aa""bb""cc""dd""ff"); 
  18. SumNew(3, 1, 2, 3); 
  19. SumStrNew(3, "12""34""56"); 
  20. string s1("hello "); 
  21. string s2("world "); 
  22. string s3("!"); 
  23. SumStdString(3, s1, s2, s3); 
  24. system("pause"); 
  25. return 0; 

運(yùn)行結(jié)果如下:

可以看到即使傳入的可變參數(shù)是std::string, 依然可以正常工作。

我們可以反匯編下看看這種情況下的參數(shù)傳遞過程:

很多時(shí)候編譯器在傳遞類對象時(shí),即使是傳值,也會在堆棧上通過push對象地址的方式來傳遞,但是上面顯然沒有這么做,因?yàn)樗獫M足可變參數(shù)的調(diào)用約定,

另外,可以看到最后在調(diào)用sumStdString后,由add esp, 58h來外部清棧。

一個(gè)std::string大小是28, 58h = 88 = 28 + 28 + 28 + 4.

從上面的例子我們可以看到,對于可變參數(shù)的函數(shù),有2種東西需要確定,一是可變參數(shù)的數(shù)量, 二是可變參數(shù)的類型,上面的例子中,參數(shù)數(shù)量我們是在第一個(gè)參數(shù)指定的,參數(shù)類型我們是自己約定的。這種方式在實(shí)際使用中顯然是不方便,于是我們就有了_vsprintf, 我們根據(jù)一個(gè)格式化字符串的來表示可變參數(shù)的類型和數(shù)量,比如C教程中入門就要學(xué)習(xí)printf, sprintf等。

總的來說可變參數(shù)給我們提供了很高的靈活性和方便性,但是也給會造成不確定性,降低我們程序的安全性,很多時(shí)候可變參數(shù)數(shù)量或類型不匹配,就會造成一些不容察覺的問題,只有更好的理解它背后的原理,我們才能更好的駕馭它。

原文鏈接:http://www.cnblogs.com/weiym/archive/2012/09/18/2689917.html

【編輯推薦】

責(zé)任編輯:彭凡 來源: 博客園
相關(guān)推薦

2021-01-06 05:29:04

C語言參數(shù)應(yīng)用

2011-04-21 17:32:15

CC++

2010-02-03 15:06:02

C++可變參數(shù)表

2011-04-21 16:57:56

staticextern

2009-09-04 17:34:11

C#CC++

2011-05-13 17:25:34

C

2011-07-14 10:39:08

強(qiáng)制類型轉(zhuǎn)換函數(shù)C++

2010-01-21 14:07:14

CC++聲明

2011-04-08 09:52:44

C++C#DLL

2010-01-27 16:05:06

C++堆棧

2010-01-21 09:34:57

C++語法

2010-01-28 16:31:54

C++類型

2010-01-25 10:25:19

C++變量

2010-01-27 17:16:52

C++構(gòu)造函數(shù)

2010-01-21 13:33:44

C++基類

2020-08-21 13:20:36

C++If ElseLinux

2010-01-20 10:19:55

C++數(shù)組

2010-01-26 10:42:26

C++函數(shù)

2023-11-17 14:10:08

C++函數(shù)

2011-08-05 09:33:30

Func局部變量作用域
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號

国产精品久久久久久久av大片| 久热av在线| 欧美www视频在线观看| 亚洲va国产va欧美va观看| 精品一区在线播放| 亚洲国产无线乱码在线观看| 欧美激情电影| 欧美不卡在线视频| 精品国产乱码久久久久久久久| 337p日本欧洲亚洲大胆色噜噜| 亚洲aⅴ天堂av在线电影软件| 中文字幕人成人乱码亚洲电影| 欧美在线高清| 亚洲福利视频免费观看| 久久精品影视大全| 国产在线看片| 国产不卡视频在线播放| 69久久夜色精品国产69| 色噜噜噜噜噜噜| 粉嫩久久久久久久极品| 亚洲成a人片在线观看中文| 日韩国产高清一区| 人妻偷人精品一区二区三区| 老汉av免费一区二区三区| 高清一区二区三区四区五区 | 久久精品亚洲一区二区| 日韩中文字幕视频在线观看| 亚洲熟女乱综合一区二区三区| 91精品店在线| 亚洲一区二区三区激情| 中文字幕一区二区三区精彩视频| 人妻一区二区三区免费| 蜜桃av噜噜一区| 国产91九色视频| 久久高清免费视频| 午夜日韩电影| 久久精品99国产精品酒店日本 | 一区二区三区视频免费观看| 91精品午夜视频| 日韩av资源在线| 欧美hdxxxx| 国产精品天干天干在观线| 加勒比在线一区二区三区观看 | 日韩精品中文字幕在线| 亚洲日本久久久| 啪啪av大全导航福利综合导航| 亚洲日本中文| 成人精品国产福利| 国产精品久久久久久久久久久新郎 | 国产伦精品一区二区三区视频免费 | 午夜不卡视频| 欧美激情一区二区在线| 精品一区二区三区视频日产| 六月婷婷中文字幕| 国产东北露脸精品视频| 91久久国产婷婷一区二区| 亚洲一区中文字幕永久在线| 视频一区二区不卡| 色综合久久久888| 天堂av免费在线| 国产国产精品| 久久精品视频播放| 中文字幕第69页| 清纯唯美综合亚洲| 一本色道久久88亚洲综合88| 麻豆av一区| 欧美日韩在线视频一区二区三区| jizzjizz亚洲| 一区二区三区四区亚洲| 国产精品无码电影在线观看| 久久大胆人体| 精品日韩中文字幕| 国产一级不卡毛片| 欧美aaaaaa| 欧美一区日本一区韩国一区| 男人的天堂免费| 精品综合久久88少妇激情| 亚洲精品国偷自产在线99热| japanese中文字幕| 日韩www.| 欧美极品少妇全裸体| 久久精品第一页| 亚洲一区二区免费看| 色综合久久中文字幕综合网小说| 国产一级淫片a| 日日欢夜夜爽一区| 亚洲一区二区三区视频播放| 免费看国产片在线观看| proumb性欧美在线观看| 精品一区国产| 国产区在线观看| 精品久久久久久电影| 精品国产成人系列| 日本三日本三级少妇三级66| 在线免费观看污| 亚洲一区二区三区四区在线| 免费av网址在线| 精品一区二区三区四区五区 | www午夜视频| 国产一区二区三区免费观看在线| 亚洲国产精品一区二区久| 91成人在线免费视频| 在线中文一区| 欧美激情久久久| 国产天堂第一区| 丁香婷婷综合网| 视频一区二区三区免费观看| 波多野结衣精品| 欧美日韩国产一二三| www.成人黄色| 亚洲小说图片视频| 欧美老肥婆性猛交视频| 凹凸精品一区二区三区| 国产成人av电影在线| 精品国产一区二区三区日日嗨| 搞黄视频在线观看| 日韩午夜激情| 精品欧美一区二区三区| 中文字幕在线综合| 久久亚洲国产精品尤物| 亚洲精品电影网站| 国产不卡在线观看视频| 在线综合亚洲| 91免费在线视频| 丰满人妻一区二区三区免费视频| 中文天堂在线一区| 亚洲 欧美 综合 另类 中字| 日韩福利一区| 日韩电影免费在线观看中文字幕 | 欧美国产精品人人做人人爱| 日本成人一级片| 久久久亚洲综合| 国产精品网站免费| 榴莲视频成人app| 亚洲精品美女视频| 国产一级视频在线播放| 亚洲一区久久| 久久综合福利| 精品三级久久| 精品乱码亚洲一区二区不卡| 精品人体无码一区二区三区| 亚洲自拍另类| 欧美极品视频一区二区三区| 深夜福利视频一区二区| 日韩欧美国产一区二区在线播放 | 国产福利免费在线观看| 午夜一区二区三区视频| 91亚洲一线产区二线产区 | 国产亚洲精品久久久久久久| 国产人与zoxxxx另类91| 亚洲图片在区色| 五月婷婷开心网| 2020国产精品自拍| 四虎永久在线精品无码视频| 国产成人精品免费视| 国产成人精品一区二区三区| 国产一二在线观看| 国产一二区在线| 狠狠色狠色综合曰曰| 黄色片免费网址| 综合国产精品| 99久久精品免费看国产一区二区三区 | 免费在线观看黄色av| 狠狠色伊人亚洲综合成人| 日韩av影视| 肉色欧美久久久久久久免费看| 亚洲欧洲日本专区| 日本成人一级片| 亚洲欧美日韩在线播放| 永久免费黄色片| 欧美午夜久久| 欧美激情专区| 亚洲欧洲二区| 久久久久久亚洲| 青青久在线视频| 日韩欧美在线免费观看| 五月婷婷六月香| 国产精品一区免费视频| 九一国产精品视频| 国产一区二区精品福利地址| 成人黄色免费在线观看| 色在线视频网| 亚洲欧洲日产国产网站| 国产精品色综合| 午夜国产不卡在线观看视频| 亚洲理论片在线观看| 国产在线看一区| 蜜臀av色欲a片无码精品一区| 综合综合综合综合综合网| 国产欧亚日韩视频| a视频网址在线观看| 91麻豆精品国产91久久久久| 日本熟妇毛茸茸丰满| 成人免费视频播放| 精品久久久久久中文字幕2017| 国产欧美日韩免费观看| 亚洲伊人久久综合| 日本不卡一二三| 国产亚洲精品美女| a级片在线视频| 欧美性xxxx极品hd欧美风情| 国产极品美女在线| 91麻豆免费视频| 亚洲欧美日韩直播| 2022亚洲天堂| 日韩片欧美片| 51成人做爰www免费看网站| 韩日毛片在线观看| 伊人伊成久久人综合网小说| 欧美性猛交 xxxx| 欧洲一区二区三区免费视频| 久草免费在线视频观看| 国产精品久久久久久久久免费丝袜| 无码av免费精品一区二区三区| 免费av成人在线| 免费无码国产v片在线观看| 中文字幕乱码亚洲无线精品一区| 精品一卡二卡三卡四卡日本乱码| 草莓视频成人appios| 97色在线观看| 91se在线| 亚洲精品成a人在线观看| 一级片在线免费观看视频| 亚洲美女免费在线| 91成人在线免费视频| 91在线码无精品| 扒开伸进免费视频| 国产老肥熟一区二区三区| 午夜视频你懂的| 久久精品三级| 亚洲人成色77777| 亚洲精品护士| av在线观看地址| 一区二区中文字| 免费看啪啪网站| 爽成人777777婷婷| 欧美日韩亚洲免费| 妖精视频一区二区三区免费观看| 91在线视频精品| 亚洲黑人在线| 国产成人亚洲精品| 一呦二呦三呦精品国产| 日韩av手机在线观看| 筱崎爱全乳无删减在线观看| 2019国产精品自在线拍国产不卡| 性欧美ⅴideo另类hd| 久久精品成人欧美大片古装| 婷婷国产在线| 亚洲第五色综合网| 精品国产999久久久免费| 91精品国产综合久久久久久久 | 在线黄色网页| 神马久久久久久| 免费av在线| 久久成人国产精品| 激情小视频网站| 高清一区二区| 成人免费福利在线| japansex久久高清精品| 国产精品一区二区久久久久| 国产原创一区| 91精品久久久久久久久中文字幕| 欧美视频免费看| 亚洲淫片在线视频| 久久久免费毛片| 免费国产一区二区| 久久av免费看| 亚洲午夜久久久影院伊人| 亚洲精品成人| 国产人妻777人伦精品hd| 亚洲欧美日韩在线观看a三区| 国产日韩av网站| 久久精品麻豆| 波多野结衣国产精品| 日日噜噜夜夜狠狠视频欧美人| 欧美日韩亚洲自拍| 免费人成精品欧美精品| 日韩av在线中文| 国产91精品欧美| 永久免费看mv网站入口78| 亚洲国产电影在线观看| 手机在线中文字幕| 亚洲成国产人片在线观看| 国产suv精品一区二区33| 欧美人动与zoxxxx乱| 99久久久久成人国产免费| 亚洲精品国产精品自产a区红杏吧| 国产h在线观看| 欧美另类老女人| 综合日韩av| 91深夜福利视频| 亚洲+变态+欧美+另类+精品| 欧美少妇一区| 欧美午夜久久| 无人在线观看的免费高清视频| 国产一区免费电影| 久久久国产精品无码| 国产欧美日韩亚州综合| 97精品在线播放| 欧美性xxxx极品hd欧美风情| 精品国产av一区二区| 亚洲美女在线看| 肉肉视频在线观看| 国产精品久久久久久婷婷天堂| 国产第一亚洲| 久久综合给合久久狠狠色| 色乱码一区二区三区网站| 国产日韩av网站| 国产在线不卡视频| 夜夜春很很躁夜夜躁| 亚洲1区2区3区视频| 国产精品久久无码一三区| 亚洲国产精品小视频| 中文字幕在线观看播放| 久久国产精品一区二区| 日本一区二区久久精品| 午夜电影亚洲| 中文字幕第38页| 国产亚洲制服色| 三级黄色在线视频| 欧美久久久一区| yw在线观看| 欧洲日本亚洲国产区| 久久久久久亚洲精品美女| 秋霞毛片久久久久久久久| 亚洲精品乱码久久久久久蜜桃麻豆| 男女视频在线看| 久久久午夜精品理论片中文字幕| 欧美日韩在线观看免费| 欧美狂野另类xxxxoooo| 国产尤物视频在线| 欧美一级淫片aaaaaaa视频| 大伊香蕉精品在线品播放| 中文字幕剧情在线观看一区| 日韩一区精品字幕| 最新在线黄色网址| 一区二区三区免费观看| 国产露脸91国语对白| 一本色道久久综合狠狠躁篇怎么玩 | 欧美一区二区大胆人体摄影专业网站| 国产精品毛片aⅴ一区二区三区| 亚洲不卡1区| 蜜桃久久精品一区二区| 天天摸日日摸狠狠添| 91国内精品野花午夜精品| 黄色av免费在线看| 国产成人精品av| 成人精品视频| 国产色视频在线播放| 中文字幕视频一区二区三区久| 亚洲中文字幕无码爆乳av| 亚洲美女在线视频| 亚洲国产尤物| 亚洲精品无人区| 国产曰批免费观看久久久| 91免费公开视频| 欧美一级艳片视频免费观看| 美女国产在线| 91av免费看| 你懂的亚洲视频| 毛茸茸free性熟hd| 欧美视频一区二区三区…| 日韩欧美亚洲系列| 国产精品久久久久久久久久ktv| 日韩中文首页| 波多野结衣中文字幕在线播放| 夜夜夜精品看看| 人妻一区二区三区四区| 欧美一级黄色网| 妖精视频一区二区三区免费观看| 精品999在线| 国产日韩精品久久久| 好吊妞www.84com只有这里才有精品| 色婷婷综合久久久久久| 黄色免费观看视频网站| 国产69精品久久久久毛片| 少妇一级淫片免费放中国 | 黄色成人av网| 九色在线播放| 国产精品成人一区| 91精品国产乱码久久久久久| 中文 日韩 欧美| 福利一区福利二区微拍刺激| sese在线视频| 国产精品免费观看高清| 久久国产主播| 欧美日韩中文字幕在线观看| 亚洲精品二三区| 777午夜精品电影免费看| 少妇久久久久久被弄到高潮| 久久久一区二区| xxxx18国产| 国产精品爱啪在线线免费观看 | 中日韩美女免费视频网址在线观看 | 国产v亚洲v天堂无码| 欧美精品导航| theav精尽人亡av| 日韩一区二区高清| 欧美国产大片| 国产日韩亚洲欧美在线|