va_start和va_end使用詳解,va_startva_end

來源:互聯網
上載者:User

va_start和va_end使用詳解,va_startva_end

本文主要介紹va_start和va_end的使用及原理。

  介紹這兩個宏之前先看一下C中傳遞函數的參數時的用法和原理: 

1.在C中,當我們無法列出傳遞函數的所有實參的類型和數目時,可以用省略符號指定參數表

void foo(...);
void foo(parm_list,...);這種方式和我們以前認識的不大一樣,但我們要記住這是C中一種傳參的形式,在後面我們就會用到它。

 

2.函數參數的傳遞原理

  函數參數是以資料結構:棧的形式存取,從右至左入棧。

  首先是參數的記憶體存放格式:參數存放在記憶體的堆棧段中,在執行函數的時候,從最後一個開始入棧。因此棧底高地址,棧頂低地址,舉個例子如下:
void func(int x, float y, char z);
  那麼,調用函數的時候,實參 char z 先進棧,然後是 float y,最後是 int x,因此在記憶體中變數的存放次序是 x->y->z,因此,從理論上說,我們只要探測到任意一個變數的地址,並且知道其他變數的類型,通過指標移位元運算,則總可以順藤摸瓜找到其他的輸入變數。  下面是 <stdarg.h> 裡面重要的幾個宏定義如下:
typedef char* va_list;
void va_start ( va_list ap, prev_param ); /* ANSI version */
type va_arg ( va_list ap, type ); 
void va_end ( va_list ap ); 
va_list 是一個字元指標,可以理解為指向當前參數的一個指標,取參必須通過這個指標進行。
<Step 1> 在調用參數表之前,定義一個 va_list 類型的變數,(假設va_list 類型變數被定義為ap);
<Step 2> 然後應該對ap 進行初始化,讓它指向可變參數表裡面的第一個參數,這是通過 va_start 來實現的,第一個參數是 ap 本身,第二個參數是在變參表前面緊挨著的一個變數,即“...”之前的那個參數;
<Step 3> 然後是擷取參數,調用va_arg,它的第一個參數是ap,第二個參數是要擷取的參數的指定類型,然後返回這個指定類型的值,並且把 ap 的位置指向變參表的下一個變數位置;
<Step 4> 擷取所有的參數之後,我們有必要將這個 ap 指標關掉,以免發生危險,方法是調用 va_end,他是輸入的參數 ap 置為 NULL,應該養成擷取完參數表之後關閉指標的習慣。說白了,就是讓我們的程式具有健壯性。通常va_start和va_end是成對出現。例如 int max(int n, ...); 其函數內部應該如此實現:
#include <iostream.h> 
void fun(int a, ...) 

  int *temp = &a;  temp++;

  for (int i = 0; i < a; ++i) 
  { 
    cout << *temp << endl; 
    temp++; 
  } 
}
int main() 

  int a = 1; 
  int b = 2; 
  int c = 3; 
  int d = 4; 
  fun(4, a, b, c, d); 
  system("pause"); 
  return 0; 

Output:: 



4

3:擷取省略符號指定的參數
  在函數體中聲明一個va_list,然後用va_start函數來擷取參數列表中的參數,使用完畢後調用va_end()結束。像這段代碼: 
void TestFun(char* pszDest, int DestLen, const char* pszFormat, ...) 

va_list args; 
va_start(args, pszFormat); //一定要“...”之前的那個參數
_vsnprintf(pszDest, DestLen, pszFormat, args); 
va_end(args); 
} 4.示範如何使用參數個數可變的函數,採用ANSI標準形式 
#include 〈stdio.h〉 
#include 〈string.h〉 
#include 〈stdarg.h〉 

/*函數原型聲明,至少需要一個確定的參數,注意括弧內的省略符號*/ 
int demo( char, ... ); 
void main( void ) 

   demo("DEMO", "This", "is", "a", "demo!", ""); 


/*ANSI標準形式的聲明方式,括弧內的省略符號表示選擇性參數*/ 
int demo( char msg, ... ) 

       /*定義儲存函數參數的結構*/
   va_list argp; 
   int argno = 0; 
   char para; 
     /*argp指向傳入的第一個選擇性參數,msg是最後一個確定的參數*/ 
   va_start( argp, msg ); 
   while (1) 
       { 
        para = va_arg( argp, char); 
           if ( strcmp( para, "") == 0 ) 
               break; 
           printf("Parameter #%d is: %s\n", argno, para); 
           argno++; 

va_end( argp ); 
/*將argp置為NULL*/
return 0; 
}

 以上是對va_start和va_end的介紹。

 

轉載地址:http://www.cnblogs.com/hanyonglu/archive/2011/05/07/2039916.html 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.