C/C++中帶可變參數的函數


1.帶可變參數的函數由來

函數中的參數個數不確定時,這時候就需要帶可變參數的函數!

如我們經常使用的C庫函數printf()實際就是一個可變參數的函數,

其原型為:

 
 int   printf(   const   char*   format,   ...);

它除了有一個參數format固定以外,后面跟的參數的個數和類型是可變的。例如我們可以有以下不同的調用方法:

 

printf( "%d ",i);   
printf( "%s ",s);   
printf( "the   number   is   %d   ,string   is:%s ",   i,   s);   

 

2.帶可變參數函數的實現,

原理:

  • 使用了指針參數來解決參數的可變問題,指針參數隨着其移動指向不同的參數;
  • C語言的函數形參是從右向左壓入堆棧的,以保證棧頂是第一個參數。

 

 

C語言標准庫中頭文件stdarg.h索引的接口包含了一組能夠遍歷變長參數列表的宏。

頭文件

#include <stdarg.h>

幾個宏

(1).  va_list  定義一個指針

用來定義一個表示參數表中各個參數變量,即定義了一個指向參數的指針, 用於指示可選的參數.

如:va_list ap;

(2). va_start(ap,v)  初始化指針  

使參數列表指針ap指向函數參數列表中的第一個可選參數v是位於第一個可選參數之前的固定參數, 或者說最后一個固定參數.通常用於指定可變參數列表中參數的個數!

如有一va函數的聲明是void va_test(char a, char b, char c, ...), 則它的固定參數依次是a,b,c, 最后一個固定參數v為c, 因此就是va_start(ap, c).

 
        

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

 

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

 

例:

#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;   
}
/*

輸出為

 
         

100 4193388 ?
100 200 ?
100 200 a

*/

 

 

 

 思路:

(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語言的方式來實現。

 

參考

http://www.jb51.net/article/41868.htm


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM