1、由於在c語言中沒有函式過載,解決不定數目函式引數問題變得比較麻煩;即使採用c++,如果引數個數不能確定,也很難採用函式過載.
對這種情況,有些人採用指標引數來解決問題.下面就c語言中處理不定引數數目的問題進行討論.
2、下面是 裡面重要的幾個巨集定義如下:
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 是乙個字元指標,可以理解為指向當前引數的乙個指標,取參必須通過這個指標進行。
3、函式引數是以棧的形式訪問,從右至左入棧。
舉個例子如下:void func(int x, float y, char z);
呼叫函式的時候,實參 char z 先進棧,然後是 float y,最後是 int x,因此在記憶體中變數的存放次序是 x->y->z,因此,從理論上說,我們只要探測到任意乙個變數的位址,並且知道其他變數的型別,通過指標移位運算,則總可以找到其他的輸入變數。
4、例項
#include#includevoid arg_test(int i, ...)
int main(int argc,char *argv)
5、讀取可變引數的過程其實就是堆疊中,使用指標,遍歷堆疊段中的引數列表,從低位址到高位址乙個乙個地把引數內容讀出來的過程.
6、雖然可以通過在堆疊中遍歷引數列表來讀出所有的可變引數,但是由於不知道可變引數有多少個,什麼時候應該結束遍歷,如果在堆疊中遍歷太多,那麼很可能讀取一些無效的資料.
解決辦法:a.可以在第乙個起始引數中指定引數個數,那麼就可以在迴圈還中讀取所有的可變引數;
b.定義乙個結束標記,在呼叫函式的時候,在最後乙個引數中傳遞這個標記,這樣在遍歷可變引數的時候,可以根據這個標記結束可變引數的遍歷;
7、典型應用:printf的實現
#include /* minprintf: minimal printf with variable argument list */
void minprintf(char *fmt, ...)
switch (*++p)
}va_end(ap); /* clean up when done */
}
va start和va end使用詳解
本文主要介紹va start和va end的使用及原理。在以前的一篇帖子format messagebox 詳解 中曾使用到va start和va end這兩個巨集,但對它們也只是泛泛的了解。介紹這兩個巨集之前先看一下c中傳遞函式的引數時的用法和原理 1.在c中,當我們無法列出傳遞函式的所有實參的型...
va start和va end使用詳解
介紹這兩個巨集之前先看一下c中傳遞函式的引數時的用法和原理 1.在c中,當我們無法列出傳遞函式的所有實參的型別和數目時,可以用省略號指定參數列 void foo void foo parm list,這種方式和我們以前認識的不大一樣,但我們要記住這是c中一種傳參的形式,在後面我們就會用到它。2.函式...
va start和va end使用詳解
本文主要介紹va start和va end的使用及原理。在以前的一篇帖子format messagebox 詳解 中曾使用到va start和va end這兩個巨集,但對它們也只是泛泛的了解。介紹這兩個巨集之前先看一下c中傳遞函式的引數時的用法和原理 1.在c中,當我們無法列出傳遞函式的所有實參的型...