關(guān)于C/C++中可變參數(shù)的詳細(xì)介紹(va_list,va_start,va_arg,va_end)
由于在C語(yǔ)言中沒(méi)有函數(shù)重載,解決不定數(shù)目函數(shù)參數(shù)問(wèn)題變得比較麻煩,即使采用C++,如果參數(shù)個(gè)數(shù)不能確定,也很難采用函數(shù)重載。對(duì)這種情況,提出了指針參數(shù)來(lái)解決問(wèn)題。
如printf()函數(shù),其原型為:
int printf( const char* format, ...);
它除了有一個(gè)參數(shù)format固定以外,后面跟的參數(shù)的個(gè)數(shù)和類(lèi)型是可變的,例如我們可以有以下不同的調(diào)用方法:
printf( "%d ",i);
printf( "%s ",s);
printf( "the number is %d ,string is:%s ", i, s);
如何實(shí)現(xiàn)其功能?
我們需要以下幾個(gè)宏定義:
(1)va_list
定義了一個(gè)指針arg_ptr, 用于指示可選的參數(shù).
(2)va_start(arg_ptr, argN)
使參數(shù)列表指針arg_ptr指向函數(shù)參數(shù)列表中的第一個(gè)可選參數(shù),argN是位于第一個(gè)可選參數(shù)之前的固定參數(shù), 或者說(shuō)最后一個(gè)固定參數(shù).如有一va函數(shù)的聲明是void va_test(char a, char b, char c, ...), 則它的固定參數(shù)依次是a,b,c, 最后一個(gè)固定參數(shù)argN為c, 因此就是va_start(arg_ptr, c).
(3)va_arg(arg_ptr, type)
返回參數(shù)列表中指針arg_ptr所指的參數(shù), 返回類(lèi)型為type. 并使指針arg_ptr指向參數(shù)列表中下一個(gè)參數(shù).返回的是可選參數(shù), 不包括固定參數(shù).
(4)va_end(arg_ptr)
清空參數(shù)列表, 并置參數(shù)指針arg_ptr無(wú)效.
(注:va在這里是variable-argument(可變參數(shù))的意思. 這些宏定義在stdarg.h中,所以用到可變參數(shù)的程序應(yīng)該包含這個(gè)頭文件)
也需你現(xiàn)在還是不能理解,別著急,現(xiàn)在從一個(gè)實(shí)例著手.定義這么一個(gè)函數(shù),函數(shù)的第一個(gè)參數(shù)是固定的,其余參數(shù)是可變的。定義為:
void simple_va_fun(int i,...); 其代碼為:
#include <iostream>
#include <stdarg.h>
using namespace std;
void simple_va_fun(int i,...);
int main(int argc,char *argv[])
{
simple_va_fun(100);
simple_va_fun(100,200);
simple_va_fun(100,200,'a');
return 0;
}
void simple_va_fun(int i,...)
{
va_list arg_ptr; //定義可變參數(shù)指針
va_start(arg_ptr,i); // i為最后一個(gè)固定參數(shù)
int j=va_arg(arg_ptr,int); //返回第一個(gè)可變參數(shù),類(lèi)型為int
char c=va_arg(arg_ptr,char); //返回第二個(gè)可變參數(shù),類(lèi)型為char
va_end(arg_ptr); // 清空參數(shù)指針
printf( "%d %d %c\n",i,j,c);
return;
}
代碼運(yùn)行解釋:
(1)首先在函數(shù)里定義一個(gè)va_list型的變量,這里是arg_ptr,這個(gè)變量是指向參數(shù)的指針.
(2)然后用va_start宏初始化變量arg_ptr,這個(gè)宏的第二個(gè)參數(shù)是第一個(gè)可變參數(shù)的前一個(gè)參數(shù),是一個(gè)固定的參數(shù).
(3)然后用va_arg返回第一個(gè)可變的參數(shù),并賦值給整數(shù)j。va_arg的第二個(gè)參數(shù)是你要返回的參數(shù)的類(lèi)型,這里是int型. 返回第一個(gè)可變參數(shù)后arg_ptr指向第二個(gè)可變參數(shù),用同樣的方法返回并賦值給c,類(lèi)型為char類(lèi)型。
(4)最后用va_end宏結(jié)束可變參數(shù)的獲取。
小結(jié):
可變參數(shù)的函數(shù)原理其實(shí)很簡(jiǎn)單,而va系列是以宏定義來(lái)定義的,實(shí)現(xiàn)跟堆棧相關(guān).我們寫(xiě)一個(gè)可變函數(shù)的C函數(shù)時(shí),有利也有弊,所以在不必要的場(chǎng)合,我們無(wú)需用到可變參數(shù).如果在C++里,我們應(yīng)該利用C++的多態(tài)性來(lái)實(shí)現(xiàn)可變參數(shù)的功能,盡量避免用C語(yǔ)言的方式來(lái)實(shí)現(xiàn)。
附加:
參數(shù)在堆棧中分布:
在進(jìn)程中,堆棧地址是從高到低分配的.當(dāng)執(zhí)行一個(gè)函數(shù)的時(shí)候,將參數(shù)列表入棧,壓入堆棧的高地址部分,然后入棧函數(shù)的返回地址,接著入棧函數(shù)的執(zhí)行代碼,這個(gè)入棧過(guò)程,堆棧地址不斷遞減,一些黑客就是在堆棧中修改函數(shù)返回地址,執(zhí)行自己的代碼來(lái)達(dá)到執(zhí)行自己插入的代碼段的目的. 總之,函數(shù)在堆棧中的分布情況是:地址從高到低,依次是:函數(shù)參數(shù)列表,函數(shù)返回地址,函數(shù)執(zhí)行代碼段. 堆棧中,各個(gè)函數(shù)的分布情況是倒序的.即最后一個(gè)參數(shù)在列表中地址最高部分,第一個(gè)參數(shù)在列表地址的最低部分.參數(shù)在堆棧中的分布情況如下:
最后一個(gè)參數(shù)
倒數(shù)第二個(gè)參數(shù)
...
第一個(gè)參數(shù)
函數(shù)返回地址
函數(shù)代碼段
上一篇:C++類(lèi)的靜態(tài)成員初始化詳細(xì)講解
欄 目:C語(yǔ)言
下一篇:成員初始化列表與構(gòu)造函數(shù)體中的區(qū)別詳細(xì)解析
本文標(biāo)題:關(guān)于C/C++中可變參數(shù)的詳細(xì)介紹(va_list,va_start,va_arg,va_end)
本文地址:http://mengdiqiu.com.cn/a1/Cyuyan/4032.html
您可能感興趣的文章
- 04-02func函數(shù)+在C語(yǔ)言 func函數(shù)在c語(yǔ)言中
- 04-02c語(yǔ)言中對(duì)數(shù)函數(shù)的表達(dá)式 c語(yǔ)言中對(duì)數(shù)怎么表達(dá)
- 04-02c語(yǔ)言沒(méi)有round函數(shù) round c語(yǔ)言
- 04-02C語(yǔ)言中怎么打出三角函數(shù) c語(yǔ)言中怎么打出三角函數(shù)的值
- 01-10深入理解C++中常見(jiàn)的關(guān)鍵字含義
- 01-10使用C++實(shí)現(xiàn)全排列算法的方法詳解
- 01-10深入Main函數(shù)中的參數(shù)argc,argv的使用詳解
- 01-10APUE筆記之:進(jìn)程環(huán)境詳解
- 01-10c++中inline的用法分析
- 01-10如何尋找數(shù)組中的第二大數(shù)


閱讀排行
- 1C語(yǔ)言 while語(yǔ)句的用法詳解
- 2java 實(shí)現(xiàn)簡(jiǎn)單圣誕樹(shù)的示例代碼(圣誕
- 3利用C語(yǔ)言實(shí)現(xiàn)“百馬百擔(dān)”問(wèn)題方法
- 4C語(yǔ)言中計(jì)算正弦的相關(guān)函數(shù)總結(jié)
- 5c語(yǔ)言計(jì)算三角形面積代碼
- 6什么是 WSH(腳本宿主)的詳細(xì)解釋
- 7C++ 中隨機(jī)函數(shù)random函數(shù)的使用方法
- 8正則表達(dá)式匹配各種特殊字符
- 9C語(yǔ)言十進(jìn)制轉(zhuǎn)二進(jìn)制代碼實(shí)例
- 10C語(yǔ)言查找數(shù)組里數(shù)字重復(fù)次數(shù)的方法
本欄相關(guān)
- 04-02c語(yǔ)言函數(shù)調(diào)用后清空內(nèi)存 c語(yǔ)言調(diào)用
- 04-02func函數(shù)+在C語(yǔ)言 func函數(shù)在c語(yǔ)言中
- 04-02c語(yǔ)言的正則匹配函數(shù) c語(yǔ)言正則表達(dá)
- 04-02c語(yǔ)言用函數(shù)寫(xiě)分段 用c語(yǔ)言表示分段
- 04-02c語(yǔ)言中對(duì)數(shù)函數(shù)的表達(dá)式 c語(yǔ)言中對(duì)
- 04-02c語(yǔ)言編寫(xiě)函數(shù)冒泡排序 c語(yǔ)言冒泡排
- 04-02c語(yǔ)言沒(méi)有round函數(shù) round c語(yǔ)言
- 04-02c語(yǔ)言分段函數(shù)怎么求 用c語(yǔ)言求分段
- 04-02C語(yǔ)言中怎么打出三角函數(shù) c語(yǔ)言中怎
- 04-02c語(yǔ)言調(diào)用函數(shù)求fibo C語(yǔ)言調(diào)用函數(shù)求
隨機(jī)閱讀
- 01-11Mac OSX 打開(kāi)原生自帶讀寫(xiě)NTFS功能(圖文
- 08-05織夢(mèng)dedecms什么時(shí)候用欄目交叉功能?
- 01-10SublimeText編譯C開(kāi)發(fā)環(huán)境設(shè)置
- 08-05dedecms(織夢(mèng))副欄目數(shù)量限制代碼修改
- 01-10delphi制作wav文件的方法
- 01-11ajax實(shí)現(xiàn)頁(yè)面的局部加載
- 04-02jquery與jsp,用jquery
- 01-10C#中split用法實(shí)例總結(jié)
- 01-10使用C語(yǔ)言求解撲克牌的順子及n個(gè)骰子
- 08-05DEDE織夢(mèng)data目錄下的sessions文件夾有什