變長參數

轉載自: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;  
}  



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

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

?

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

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/258945.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/258945.shtml
英文地址,請注明出處:http://en.pswp.cn/news/258945.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

第十七章 我國農業科學技術

農村改革解說(專著)第十七章 第十七章 我國農業科學技術 1、為什么說科學技術是生產力? 我們說科學技術是生產力,是因為在構成生產力的兩個主要因素中,都包含著科學技術在內。 A、生產力中人的因素是同一定的科學技術緊…

《淘寶網開店 拍攝 修圖 設計 裝修 實戰150招》一一1.2 選購鏡頭時應注意的事項...

本節書摘來自異步社區出版社《淘寶網開店 拍攝 修圖 設計 裝修 實戰150招》一書中的第1章,第1.2節,作者: 葛存山,更多章節內容可以訪問云棲社區“異步社區”公眾號查看。 1.2 選購鏡頭時應注意的事項 面對如此之多的鏡頭&#xf…

OpenCV中的神器Image Watch

Image Watch是在VS2012上使用的一款OpenCV工具,能夠實時顯示圖像和矩陣Mat的內容,跟Matlab很像,方便程序調試,相當好用。跟VS2012配合使用,簡直就是一款神器!讓我一下就愛上它了! 下面介紹一些鏈…

python異步_Python通過Thread實現異步

當long函數耗時較長時,需要程序先向下執行,這就需要異步,改寫代碼如下: import _thread import time def long(cb): print (long execute) def fun(callback): time.sleep(5) result long end callback(result) _thread.start_ne…

SAM4E單片機之旅——13、LCD之ASF初步

在Atmel Studio 6中,集成了Atmel Software Framework(ASF框架)。通過它提供的庫,可以很快速地完成新的項目。 這次的最終目標使用ASF在LCD上顯示出文字“Hello World!”,現階段目標是點亮LCD的背光,學習目標…

《HTML5與CSS3實戰指南》——2.2 基本的HTML5模板

本節書摘來自異步社區《HTML5與CSS3實戰指南》一書中的第2章,第2.2節,作者: 【美】Estelle Weyl , Louis Lazaris , Alexis Goldstein 更多章節內容可以訪問云棲社區“異步社區”公眾號查看。 2.2 基本的HTML5模板 在您學習HTML5和新技術時,您…

c# Message const

typeTMsg packed recordhwnd: HWND; //窗口句柄message: UINT;//消息常量標識符wParam: WPARAM ;// 32位消息的特定附加信息lParam: LPARAM ;// 32位消息的特定附加信息time: DWORD;//消息創建時的時間pt: TPoint; //消息創建時的鼠標位置end ; 消息中有什么?是否覺…

OpenCV坐標體系的初步認識

實驗基礎本次實驗通過一個簡短的例子,主要來說明下面4個問題: 1. 坐標體系中的零點坐標為圖片的左上角,X軸為圖像矩形的上面那條水平線;Y軸為圖像矩形左邊的那條垂直線。該坐標體系在諸如結構體Mat,Rect,Point中都是適用的。&…

python爬取知乎live_Python爬蟲 - 簡單抓取百度指數

前言有點忙,沒空寫東西,這是之前寫的,加了些配圖而已 這次要爬的網站是百度指數 正文 一、分析 打開網站(百度指數),呈現出來是這樣的 如果搜索的話就需要登陸了,如果沒有什么特別頻繁的請求的話,直接登陸復…

在Visual Studio上開發Node.js程序

在Visual Studio上開發Node.js程序 原文:在Visual Studio上開發Node.js程序【題外話】 最近準備用Node.js做些東西,于是找找看能否有Visual Studio上的插件以方便開發。結果還真找到了一個,來自微軟的Node.js Tools for Visual Studio(NTVS&a…

Oracle ASM 翻譯系列第十一彈:高級知識 Offline or drop?

Offline or drop? 當一個ASM磁盤不可用時,ASM會把它從磁盤組里移除,對嗎?要看情況,通常取決于ASM版本和磁盤組的冗余級別。因為一個external冗余的磁盤組會直接被dismount,所以主要關注normal和high冗余磁盤組的情況。…

net與樹莓派的情緣-安裝與卸載MySql(五)

安裝MySql sudo apt-get install mysql-server 刪除 mysql sudo apt-get autoremove --purge mysql-server-5.0sudo apt-get remove mysql-serversudo apt-get autoremove mysql-serversudo apt-get remove mysql-common //這個很重要上面的其實有一些是多余的。 清理殘留數據 …

mpls工作原理通俗解釋_用這兩種方法向最終用戶解釋NLP模型的工作原理還是不錯的...

點擊上方關注,All in AI中國上周,我看了一個關于“NLP的實踐特性工程”的演講。主要是關于LIME和SHAP在文本分類可解釋性方面是如何工作的。我決定寫一篇關于它們的文章,因為它們很有趣、易于使用,而且視覺上很吸引人。所有的機器…

向往2的年代

1. JDBC 對插入大量數據如何處理? 2. JAVA反射的使用,如何獲取一個java類的某個方法? 3. 數據庫連接池(優化) 4. 分布式事務管理轉載于:https://www.cnblogs.com/dragonflyyi/p/3564843.html

C++ limits頭文件的用法(numeric_limits)

初學C的時候,對這個模板很陌生,不知道它到底是做什么用的,今天拿起《C標準程序庫》,出現了它的討論,所以決定好好研究一番。 1. numeric_limits是什么? (A)《C標準程序庫》&#xff…

三層架構——配置文件

1、配置文件是什么? 配置文件是隨安裝程序一起被安裝到計算機上的文件,里面存放著安裝好的應用程序執行時所須要的參數。 應用程序配置文件是標準的XML文件,XML標記和屬性是區分大寫和小寫的。它能夠按須要更改,開發者可使用配置文…

《嵌入式系統開發之道——菜鳥成長日志與項目經理的私房菜》——02-04項目范圍(Scope)管理...

本節書摘來異步社區《嵌入式系統開發之道——菜鳥成長日志與項目經理的私房菜》一書中的第2章,第2.4節,作者:邱毅凌,更多章節內容可以訪問云棲社區“異步社區”公眾號查看 02-04項目范圍(Scope)管理 嵌入式…

flex(入門)之timer的使用,鍵盤,鼠標的監聽

package {import flash.display.Shape;import flash.display.Sprite;import flash.events.Event;import flash.events.KeyboardEvent;import flash.events.MouseEvent;import flash.events.TimerEvent;import flash.utils.Timer;import mx.controls.Label;//窗體大小&#xff0…

python 線程超時設置_python 條件變量Condition(36)

文章首發微信公眾號,微信搜索:猿說python對于線程與線程之間的交互我們在前面的文章已經介紹了 python 互斥鎖Lock / python事件Event , 今天繼續介紹一種線程交互方式 – 線程條件變量Condition.一.線程條件變量Condition相關函數介紹acquire() — 線程…

MsWord 操作總結

轉自(http://www.cnblogs.com/eye-like/p/4121219.html) Msdn上的word操作api(不過只有英文版,英文差的先閃過) Word2007的API:http://msdn.microsoft.com/en-us/library/bb257531(voffice.12).aspxWord201…