stdarg h編寫可變引數函式

2021-07-02 15:44:41 字數 1987 閱讀 5556

一.起因

起因是自己想寫乙個簡單的列印日誌的函式,最大的問題是,每次列印的時候輸入資料的個數是不同的。最開始的想法是用巨集,這樣就不管輸入引數多少了,但是用巨集的話就沒辦法判斷輸入引數的型別了。所以就想使用可變引數來實現,那麼問題來了,我首先得學學怎麼寫可變引數函式。吶,stdarg.h可以幫助我。

二.探索

編寫可變引數的關鍵是,va_start() ,va_arg(), va_end()這三個函式(巨集),和va_list這個型別,他們都在stdarg.h中定義。

在centos下,使用 man 3 va_start 就可以看到這三個函式的具體介紹了。

void va_start(va_list ap, last)    這個函式初始化va_list結構體ap,改結構體在後續的 va_arg()和va_end()中呼叫。第二個引數是你編寫的可變引數函式中最後乙個已知型別的引數。

type va_arg(va_list ap,type)  返回下乙個可變引數。如果該函式是va_start()後第一次呼叫,則理所當然返回的是第乙個可變引數。異常情況,如果沒有下乙個引數了或者,指定的type不匹配實際引數型別以及實際引數型別進行型別提公升 後的型別,則返回隨機錯誤。也因此需要特別的方法判斷是否還有下乙個引數。

void va_end(va_list ap) 反初始化結構體ap,與va_start()成對出現。注意在某些特殊的系統下,va_start() va_end()由巨集實現,而且分別包含乙個 ,在這種情況下必須將這兩個呼叫放在同乙個函式中。我們在任何情況下,也最好盡量這樣做。

三.例項

說了半天,改回到正題了。如何宣告乙個包含可變引數的函式呢?給個簡單的例子,

void foo(char *fmt, ...);

從上面對va_start()函式的分析中,我們可以看出,至少必須提供乙個指定型別的引數,在這裡我們就是指定了fmt。

那麼如何去解析這些可變引數呢,還是來看manual中的例子:

編寫了乙個foo函式,能夠根據 fmt中的格式,將引數列印出來。這裡的fmt就像是printf的第乙個引數一樣。

四.異常情況解決辦法

在前面介紹va_arg函式中就提到,當不存在下乙個引數的時候,會返回隨機錯誤。這點感覺挺不友好的,要是能返回個null的啥的,也好判斷嘛。okay,接下來的工作就是要解決這個可能存在的異常情況,我們要精確的控制迴圈中va_arg呼叫的次數。上面的例子,是通過fmt字串(改字串由多個's' 'd' 'c'字元組成)中,'s' 'd' 'c'的個數來控制va_arg呼叫的次數的。或者我們可以更加直接點,直接指定乙個整形引數n,比如下面的例子:

#include

#include

int mysum(int n, int * sum, ...);

int main()

printf("the sum is %d \n",sum);

} while(0);

return err; }

int mysum(int n, int * sum, ...)

va_end(ap);

return err; }

這種指定n和linux manual中指定fmt的方式,本質上是一樣的,都是已經將引數的個數n提供了,然後只需要呼叫迴圈n此就行了。我們前面提到,我們希望一種va_arg()返回null,從而判斷迴圈結束的行為方式(就像是mysql中取row一樣的方式)。預設是不提供的,但是我們可以認為的構造這樣一種行為方式,那就是

預設最後乙個傳入的引數是null。類似execl 函式。

include

#include

void print_strs(const char * first, ...);

int main()

void print_strs(const char * first, ...)

va_end(ap);

puts("");

return ; }

五.接下來要幹什麼?

回到開頭所說的,寫乙個簡單的列印日誌的函式唄!

by mzy

stdarg h 的使用 函式可變引數

全稱 standard arguments 成員 va list 用來定義va變數,如va list va。va start 使用方法 va start va,n 其中va為va list 定義的變數,n為引數個數。va arg 使用方法 va arg va,type 其中va為va list 定義...

C 可變引數 stdarg h

c語言 stdarg.h標頭檔案定義了乙個使用可變引數的方法,可以用來定義引數個數不固定的函式,其步驟如下 1.提供乙個使用省略號的函式原型 2.在函式定義中建立乙個va list型別的變數 3.用巨集 va start 把該變數初始化為乙個引數列表 4.用巨集va arg 訪問引數列表 5.用巨集...

C語言函式可變引數總結 stdarg h

stdarg.h標頭檔案中定義了一系列巨集以及資料物件,用於支援可變引數的函式。主要有 va list 定義的資料物件 用於存放可變引數列表 省略號部分 代表的參量 va start ap,v 用於將可變引數列表中第乙個參量的位址複製給va list定義的資料物件 va arg ap,t 用於訪問可...