va_list 是c語言中解決變參問題的一組巨集。
1.api介紹:
標頭檔案:
[cpp]view plain
copy
print?
#include
下面是實現變參函式的一組巨集(macro):
[cpp]view plain
copy
print?
void
va_start(
va_list
ap, last);
type va_arg(va_list
ap, type);
void
va_end(
va_list
ap);
void
va_copy(
va_list
dest,
va_list
src);
2.具體介紹:
[cpp]view plain
copy
print?
void
va_start(
va_list
ap, last);
va_start用於初始化變參結構ap,其中va_list是與變參列表相關的結構,裡面儲存著變參列表的資訊包括變參列表的指標。
last是變參函式的可變引數列表的前乙個引數,用於確定可變引數的記憶體位址;
[cpp]view plain
copy
print?
type va_arg(
va_list
ap, type);
va_arg取出當前的引數用於返回,並且把變參列表指標指向下乙個引數。其中ap是經過va_start初始化的變參結構,type是變參的型別。
[cpp]view plain
copy
print?
void
va_end(
va_list
ap);
va_end用於結束對可變引數的獲取,釋放相應的資源,將ap清零。va_end和va_start成對使用。
[cpp]view plain
copy
print?
void
va_copy(
va_list
dest,
va_list
src);
用於複製變參結構。由於具體實現不同,變參結構本身或是結構裡面的引數時指標,而簡單的賦值操作會造成淺拷貝,
當其中乙個結構的指標被釋放空間的時候(va_end釋放空間),另乙個結構的指標會成為野指標,可能就會出問題,所以對於va_list型的變數來說,禁止直接賦值(=),要用va_copy進行拷貝。
3.用法:
a.首先在函式裡定義一具va_list型的變數:
b.然後用va_start巨集初始化變數剛定義的va_list變數,這個巨集的第二個引數是第乙個可變引數的前乙個引數,是乙個固定的引數。
c.然後用va_arg返回可變的引數,va_arg的第二個引數是你要返回的引數的型別。如果函式有多個可變引數的,依次呼叫va_arg獲取各個引數。
d.最後用va_end巨集結束可變引數的獲取。
4.例子:
[html]view plain
copy
print?
#include
<
stdio.h
>
#include <
stdarg.h
>
void foo(char *fmt, ...)
va_end(ap);
}
5.使用va_list應該注意的問題:
a.可變引數的型別和個數完全由程式**控制,它並不能智慧型地識別不同引數的個數和型別;
b.由於各個平台對va_list的實現可能會用不同,所以嚴格的通過va_start、va_arg、va_end、va_copy來使用va_list很有必要,不建議直接對其進行指標操作;
c.因為編譯器對可變引數的函式的原型檢查不夠嚴格,對程式設計查錯不利。不利於我們寫出高質量的**;
d.va_start,va_arg,va_end是在c89標準中定義的。va_copy是在c99標準中定義的。
va list C語言中的可變引數
c語言中有些函式使用可變引數,比如常見的int printf const char format,第乙個引數format是固定的,其餘的引數的個數和型別都不固定。但c又無法用面相物件的函式過載的概念。不過好在c語言中定義了va list,va start va arg va end 這樣一組巨集來處...
C語言可變引數巨集
歲月不饒人,這年紀大了記憶力真是差了很多。今天寫程式需要用到可變引數的巨集,可是忘了怎麼寫,這倒也沒什麼,因為我一向是不記憶這些語法細節的,反正我知道程式裡有個地方用到了這種技巧,但是可悲的是我忘了在哪個地方。搜尋?語法都忘了蒐個p呀。只好憑著印象,在自己負責的模組 中找了一圈,花了十幾分鐘才終於在...
可變引數巨集
在 gnu c 中,巨集可以接受可變數目的引數,就象函式一樣,例如 define pr debug fmt,arg.printk kern debug fmt,arg 用可變引數巨集 variadicmacros 傳遞可變參數列 你可能很熟悉在函式中使用可變參數列,如 void printf con...