国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

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

關于C/C++中可變參數的詳細介紹(va_list,va_start,va_arg,va_end)

2020-01-26 15:47:30
字體:
來源:轉載
供稿:網友

由于在C語言中沒有函數重載,解決不定數目函數參數問題變得比較麻煩,即使采用C++,如果參數個數不能確定,也很難采用函數重載。對這種情況,提出了指針參數來解決問題。

如printf()函數,其原型為:
int   printf(   const   char*   format,   ...);

它除了有一個參數format固定以外,后面跟的參數的個數和類型是可變的,例如我們可以有以下不同的調用方法:  
printf( "%d ",i);  
printf( "%s ",s);  
printf( "the   number   is   %d   ,string   is:%s ",   i,   s);  

如何實現其功能?

我們需要以下幾個宏定義:

(1)va_list
定義了一個指針arg_ptr, 用于指示可選的參數.

(2)va_start(arg_ptr, argN)
使參數列表指針arg_ptr指向函數參數列表中的第一個可選參數,argN是位于第一個可選參數之前的固定參數, 或者說最后一個固定參數.如有一va函數的聲明是void va_test(char a, char b, char c, ...), 則它的固定參數依次是a,b,c, 最后一個固定參數argN為c, 因此就是va_start(arg_ptr, c).

(3)va_arg(arg_ptr, type)
返回參數列表中指針arg_ptr所指的參數, 返回類型為type. 并使指針arg_ptr指向參數列表中下一個參數.返回的是可選參數, 不包括固定參數.

(4)va_end(arg_ptr)
清空參數列表, 并置參數指針arg_ptr無效.

(注:va在這里是variable-argument(可變參數)的意思.   這些宏定義在stdarg.h中,所以用到可變參數的程序應該包含這個頭文件)

也需你現在還是不能理解,別著急,現在從一個實例著手.定義這么一個函數,函數的第一個參數是固定的,其余參數是可變的。定義為:
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;   //定義可變參數指針
    va_start(arg_ptr,i);   // i為最后一個固定參數
    int j=va_arg(arg_ptr,int);   //返回第一個可變參數,類型為int
    char c=va_arg(arg_ptr,char);   //返回第二個可變參數,類型為char
    va_end(arg_ptr);        //  清空參數指針
    printf( "%d %d %c/n",i,j,c);  
    return;  
}


代碼運行解釋:  
(1)首先在函數里定義一個va_list型的變量,這里是arg_ptr,這個變量是指向參數的指針.

(2)然后用va_start宏初始化變量arg_ptr,這個宏的第二個參數是第一個可變參數的前一個參數,是一個固定的參數.

(3)然后用va_arg返回第一個可變的參數,并賦值給整數j。va_arg的第二個參數是你要返回的參數的類型,這里是int型.  返回第一個可變參數后arg_ptr指向第二個可變參數,用同樣的方法返回并賦值給c,類型為char類型。

(4)最后用va_end宏結束可變參數的獲取。

小結:
可變參數的函數原理其實很簡單,而va系列是以宏定義來定義的,實現跟堆棧相關.我們寫一個可變函數的C函數時,有利也有弊,所以在不必要的場合,我們無需用到可變參數.如果在C++里,我們應該利用C++的多態性來實現可變參數的功能,盡量避免用C語言的方式來實現。

附加:

參數在堆棧中分布:
在進程中,堆棧地址是從高到低分配的.當執行一個函數的時候,將參數列表入棧,壓入堆棧的高地址部分,然后入棧函數的返回地址,接著入棧函數的執行代碼,這個入棧過程,堆棧地址不斷遞減,一些黑客就是在堆棧中修改函數返回地址,執行自己的代碼來達到執行自己插入的代碼段的目的. 總之,函數在堆棧中的分布情況是:地址從高到低,依次是:函數參數列表,函數返回地址,函數執行代碼段. 堆棧中,各個函數的分布情況是倒序的.即最后一個參數在列表中地址最高部分,第一個參數在列表地址的最低部分.參數在堆棧中的分布情況如下:

最后一個參數
倒數第二個參數
...
第一個參數
函數返回地址
函數代碼段

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 蕲春县| 陇川县| 白河县| 唐山市| 当涂县| 同仁县| 本溪| 内江市| 安泽县| 高唐县| 三亚市| 三江| 瓮安县| 新津县| 崇明县| 达拉特旗| 阿合奇县| 洛川县| 洛南县| 屯留县| 广东省| 长宁县| 偃师市| 大英县| 江永县| 永川市| 南丹县| 淳化县| 温宿县| 巴中市| 鄂尔多斯市| 灌云县| 普兰县| 大厂| 吉木乃县| 翁源县| 宜兴市| 泰宁县| 福清市| 高邮市| 龙里县|