精品欧美一区二区三区在线观看 _久久久久国色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ù)棧公眾號

欧美tk—视频vk| 国产精品黄色在线观看| 51色欧美片视频在线观看| 国产精品揄拍100视频| 99riav视频一区二区| 亚洲欧美日韩中文字幕一区二区三区| 亚洲综合自拍一区| 国产三级av片| 欧美gay男男猛男无套| 欧美成人午夜电影| 亚洲色图 在线视频| 9999在线视频| 国产精品二三区| 国产视色精品亚洲一区二区| 怡春院在线视频| 日韩视频二区| 久久久国产成人精品| 女人被狂躁c到高潮| 国产精选久久| 在线观看欧美日本| 国产精品国产亚洲精品看不卡| av国产在线观看| 99久久99久久久精品齐齐| 国产精品三级久久久久久电影| 国产在线视频二区| 五月婷婷六月综合| 国产一区二区三区久久精品| 日韩aaaaa| 中文字幕一区二区三区四区久久| 91国在线观看| 99色精品视频| 九色porny自拍视频在线观看| 亚洲日韩欧美一区二区在线| 欧日韩一区二区三区| 日本精品999| 国产精品一级片在线观看| 国产欧美一区二区白浆黑人| jizz国产在线观看| 亚洲女优在线| 91精品国产91| 日韩免费一级片| 国产伊人精品| 欧美日韩高清区| 欧美国产日韩在线观看成人| 图片区亚洲欧美小说区| 日韩在线高清视频| 天堂网av2018| 水蜜桃久久夜色精品一区| 这里只有精品在线播放| 欧美做受高潮6| 国产精品三级| 国产一区二区黑人欧美xxxx| 日韩毛片无码永久免费看| 综合国产视频| 在线日韩精品视频| 久久免费手机视频| 欧美电影免费| 久久五月天综合| 乱h高h女3p含苞待放| 88国产精品视频一区二区三区| 超碰97人人做人人爱少妇| 国产极品国产极品| 亚洲经典视频在线观看| 91精品国产99| 成人h动漫精品一区二区下载| 日韩精品成人一区二区在线| 国产精品男人爽免费视频1| 最好看的日本字幕mv视频大全| 男女性色大片免费观看一区二区| 国产精品亚洲片夜色在线| 99热这里只有精品9| 国产成人免费视频一区| 好吊色欧美一区二区三区视频| 深夜福利免费在线观看| 国产三级一区二区三区| 在线成人性视频| 麻豆av在线播放| 婷婷综合另类小说色区| 国产wwwxx| 爱情电影网av一区二区| 亚洲缚视频在线观看| 中文字幕人妻一区二区| 久久亚洲精品中文字幕蜜潮电影| 欧美乱大交xxxxx另类电影| 日韩污视频在线观看| 三级精品在线观看| 亚洲综合日韩在线| 亚洲人视频在线观看| 欧美国产精品一区二区三区| 人妻无码一区二区三区四区| 色综合桃花网| 7777精品伊人久久久大香线蕉| 四虎精品一区二区| 日韩电影免费网址| 午夜精品三级视频福利| 欧美男人天堂网| 福利一区福利二区| 日韩精品久久久| 国精一区二区三区| 在线一区二区视频| 日本久久久久久久久久| 精品一区二区三区的国产在线观看| 久久中文久久字幕| 亚洲第一网站在线观看| 国产激情一区二区三区四区| 日韩av电影免费观看| 九色91在线| 欧美日韩一区二区三区四区| 国产污在线观看| 国产精品久久观看| 日韩av电影中文字幕| 亚洲成人精品女人久久久| 中文字幕+乱码+中文字幕一区| 国产手机免费视频| 老司机精品视频网| 亚洲天堂色网站| 日本熟女一区二区| 国精产品一区一区三区mba桃花| 久久亚洲高清| gratisvideos另类灌满| 3d动漫精品啪啪1区2区免费 | 一二三区免费视频| 成人短视频下载| www.国产亚洲| 中文成人在线| 日韩中文在线中文网在线观看| 91精品国产综合久久久蜜臀九色| 国产91富婆露脸刺激对白| 免费看啪啪网站| 日本h片久久| 国产亚洲精品va在线观看| 黄色片视频网站| 成人av中文字幕| 91黄色在线看| 国产精欧美一区二区三区白种人| 欧美xxxx做受欧美护士| 亚洲国模精品私拍| 日本少妇激情舌吻| 成人免费高清在线观看| 高清无码视频直接看| 亚洲精品18| 欧美精品18videosex性欧美| www.国产三级| 一区二区三区成人| 免费高清视频在线观看| 亚洲高清影视| 成人综合网网址| 成人av福利| 日韩一区二区精品在线观看| 天天天天天天天天操| 国产一区二区在线看| 欧美日韩dvd| 粉嫩的18在线观看极品精品| 欧美激情性做爰免费视频| 亚洲av无码乱码在线观看性色| 亚洲激情在线激情| 四虎成人免费视频| 亚洲美女毛片| 就去色蜜桃综合| 美女一区网站| 中文字幕日韩欧美精品在线观看| 亚洲天堂男人网| 亚洲精品一二三| 免费看三级黄色片| 一区二区三区国产在线| 欧美人与物videos另类| 亚洲精品555| 久久艳片www.17c.com | 欧美一级二级视频| 日韩中文字幕免费视频| av加勒比在线| 午夜国产精品一区| 摸摸摸bbb毛毛毛片| 精品写真视频在线观看| 无码粉嫩虎白一线天在线观看| 亚洲电影一级片| 国产精品专区h在线观看| 黄色网在线免费观看| 亚洲第一中文字幕在线观看| 中文字幕在线播| 亚洲另类在线一区| 久久久精品人妻无码专区| 美国毛片一区二区| www.日本少妇| 日韩一区自拍| 国产精品一区二区三区不卡| 色香欲www7777综合网| 久久综合伊人77777尤物| 色婷婷av一区二区三区之红樱桃 | 亚洲污视频在线观看| 欧美成熟视频| 欧美日韩一区二区三区在线观看免| 国产成人精品一区二区三区免费| 九九热精品视频在线播放| 在线观看xxx| 91精品国产色综合久久不卡蜜臀| 国产一级18片视频| 亚洲欧洲av另类| 极品人妻一区二区三区| 国产精品羞羞答答xxdd| 91看片就是不一样| 国产精品啊v在线| 色婷婷精品国产一区二区三区| 91大神精品| 国产精品视频久久久| 日韩激情电影| 色综合久综合久久综合久鬼88 | 中文字幕亚洲区| 在线精品一区二区三区| 精品无人区卡一卡二卡三乱码免费卡 | 青青草视频网站| 麻豆久久久久久| 久久精品99国产| 影音国产精品| 四虎精品欧美一区二区免费| 精品久久久中文字幕| 国严精品久久久久久亚洲影视| 91麻豆精品国产综合久久久| 热门国产精品亚洲第一区在线| 亚洲区欧洲区| 精品国产一区二区三区久久久 | 欧美 日韩 激情| 综合一区二区三区| 亚洲视频导航| 沈樵精品国产成av片| 精品久久sese| 草草视频在线一区二区| 国产在线视频一区| 日本肉肉一区| 日韩av电影在线播放| 欧美男男tv网站在线播放| 久久久久久久久久久人体| 国产原创精品视频| zzjj国产精品一区二区| 超碰在线影院| 中文字幕国产亚洲| 国产一级在线| 亚洲香蕉成人av网站在线观看| 日韩美女一级视频| 日韩黄色在线免费观看| 四虎在线视频免费观看| 日韩午夜在线观看| 99在线无码精品入口| 欧美福利一区二区| 一级特黄aaa| 欧美乱妇20p| 国产理论片在线观看| 欧美精品 日韩| 亚洲综合一区中| 欧美日韩一级大片网址| 在线免费观看av片| 欧美日本国产视频| 国产精品人妻一区二区三区| 在线观看91av| 国产色视频在线| 日韩欧美在线综合网| 亚洲av无码一区二区三区性色| 日韩精品一区二区三区视频播放| 亚洲av无码乱码国产精品久久| 亚洲精品一区二区在线观看| 日韩一级片免费在线观看| 亚洲精品国产综合久久| 日韩亚洲视频在线观看| 亚洲欧洲国产精品| 欧洲日本在线| 欧美激情精品久久久久久久变态| 波多野结衣中文字幕久久| 午夜精品国产精品大乳美女| 丁香六月综合| 成人国产精品免费视频| 亚洲一级大片| 久久久久久国产精品一区| 国产成人影院| 亚洲国产精品影视| 尤物精品在线| 精品久久久久久中文字幕2017| 久久精品国产精品亚洲精品| xxx中文字幕| 91蜜桃在线免费视频| 纪美影视在线观看电视版使用方法| 亚洲色图视频网站| 日本视频www| 欧美日韩在线三级| 少妇精品视频一区二区| 伊人亚洲福利一区二区三区| 18videosex性欧美麻豆| 国产91精品久久久久久| 日韩在线激情| 久久精品国产精品青草色艺 | 全黄性性激高免费视频| 蜜桃伊人久久| 少妇愉情理伦片bd| 久久一区二区三区国产精品| 国产第一页浮力| 婷婷综合另类小说色区| 91丨九色丨丰满| 精品亚洲一区二区| 日本高清视频在线观看| 午夜欧美大片免费观看| julia一区二区三区中文字幕| 超碰97人人在线| 日韩精品1区| 亚洲午夜精品久久久久久人妖| 狠狠色丁香婷婷综合| aaaaa级少妇高潮大片免费看| 亚洲人成网站色在线观看| 成人毛片在线播放| 日韩女优av电影在线观看| 触手亚洲一区二区三区| 久久全国免费视频| 国产在线一区不卡| 日韩亚洲不卡在线| 亚洲精选国产| 国产精品久久久久久久99| 国产欧美视频一区二区三区| 日本一二三区视频| 91麻豆精品国产91久久久久久久久| 日色在线视频| 久久久久久欧美| 三级欧美日韩| 黄色影视在线观看| 麻豆91小视频| 亚洲av成人无码久久精品| 香蕉影视欧美成人| a天堂在线观看视频| 色噜噜久久综合伊人一本| 亚洲第一影院| 鲁丝一区鲁丝二区鲁丝三区| 一区视频在线看| 四虎国产精品免费| 亚洲欧美二区三区| 91福利在线观看视频| 亚洲视频一区二区三区| 亚洲人成午夜免电影费观看| 国产欧美日韩综合一区在线观看 | 欧美高清视频在线播放| 国产精品1区| 免费看污污视频| 国产乱子伦一区二区三区国色天香| 91av手机在线| 欧美情侣在线播放| 91成人高清| 国产精品久久久久久久久久免费| 精品免费一区二区| 91av俱乐部| 欧美极品aⅴ影院| 一区二区视频网站| 精品国产一区二区三区久久久狼| 国产精品久久久久久久久久齐齐| 色99中文字幕| 麻豆精品视频在线观看视频| www.黄色com| 制服丝袜国产精品| 91一区二区三区在线| 999日本视频| 亚洲国产影院| 亚洲第一黄色网址| 日韩欧美中文在线| 爱久久·www| 91色精品视频在线| 欧美三级网页| 鲁大师私人影院在线观看| 色一区在线观看| 在线免费观看黄色网址| 国产主播在线一区| 国色天香一区二区| 国产精品久久不卡| 欧美在线视频不卡| 黄色小网站在线观看| 成人做爰66片免费看网站| 国产精品社区| 亚洲av熟女国产一区二区性色| 欧美丰满一区二区免费视频| av黄在线观看| 精品不卡一区二区三区| 免费看的黄色欧美网站| 国产在线免费av| 精品少妇一区二区三区| 亚洲精品国产精品国产| 亚洲精品久久区二区三区蜜桃臀| 国产一区二区三区香蕉| 国产精品30p| 在线观看视频99| 成功精品影院| 欧美性猛交久久久乱大交小说| 亚洲精品免费在线播放| 亚洲人午夜射精精品日韩| 国产日韩欧美中文在线播放| 伊人久久久大香线蕉综合直播| 国产123在线| 精品嫩草影院久久| 欧美与亚洲与日本直播| 欧美视频在线第一页| 久久精品免视看| www.天堂av.com| 国产精品露脸自拍| 日韩午夜激情| 美国一级片在线观看| 日韩高清免费在线| 国产午夜精品一区在线观看|