乙個可變引數型別檢查的示例

2021-07-12 03:08:02 字數 3264 閱讀 6638

最近在修正**警告,發現封裝的列印語句不會進行引數的型別檢查,而用printf卻是可以的。於是上網找了下資料,學習了一下。

對於函式引數型別的檢查,在gcc環境中可以使用__attribute__((format(printf,n,m)))的形式。其中n表示第幾個引數是格式化字串,m指明從第幾個引數開始做檢查。對於__attribute__,等有空專門學習一下再寫篇文章出來。

下面是可變引數f的乙個簡單例子:

void

my_printf

(const

char

*fmt

,...)

;va_list vl

;va_start(vl

,fmt

);vsprintf

(buffer

,fmt,vl

);fputs

(buffer

,stdout

);va_end(vl

);}

**不複雜,使用了va_list等幾個巨集和vsprintf來實現可變引數。但呼叫my_printf不會進行引數型別檢查。

測試例子如下:

void

******_test

(void

)

我就亂用整型、指標,甚至多引數少引數,但編譯沒有警告,原因就是my_printf不夠嚴格,當然對於指標的列印,可以使用%d,但如果使用%s來列印乙個整數,就會有段錯誤,如果在編譯階段就能看到警告,就不會等到執行時才發現,特別是當**工程大,而列印語句在一定條件下才觸發,問題就更難找了。因此,對函式的引數進行嚴格的檢查是很有必要的。上例中,把宣告改為:

void

my_printf

(const

char

*fmt

,...)

__attribute__

((format

(printf,1

,2)));

這樣就解決問題了。

對於上面的示例,編譯會提到有警告,如下:

test

.cpp:in

function

『void

******_test

()』:

test

.cpp:32

:warning

:format 『%d

』expects type

『int

』,but argument

2has type

『char

*』test

.cpp:32

:warning

:format 『%s

』expects type

『char

*』,but argument

3has type

『int

』test

.cpp:33

:warning

:too few arguments

forformat

test

.cpp:34

:warning

:too many arguments

forformat

使用__attribute__((format(printf,n,m)))的函式形式基本固定,最後的引數是省略號。比如經典的api:

int

printf

(const

char

*format

,...);

intfprintf

(file

*stream

,const

char

*format

,...);

intsprintf

(char

*str

,const

char

*format

,...);

intsnprintf

(char

*str

,size_t

size

,const

char

*format

,...);

void

syslog

(int

priority

,const

char

*format

,...);

error

:format

string

argument

nota

string

type

特別要說明的是在c++類中如使用__attribute__((format(printf,n,m)))則要注意引數位置,c++預設隱藏有this指標,所以n、m的值要加1。但是類的靜態成員沒有this指標。

附上使用c++類封裝的例子:

class

myprintf

;void

myprintf

::print

(int

level

,const

char

*fmt

,...)

;va_list vl

;va_start(vl

,fmt

);vsprintf

(buffer

,fmt,vl

);printf

("[%d] "

,level

);fputs

(buffer

,stdout

);va_end(vl

);}void

myprintf

::print

(int

level

,int

level2

,const

char

*fmt

,...)

;va_list vl

;va_start(vl

,fmt

);vsprintf

(buffer

,fmt,vl

);printf

("[%d %d] "

,level

,level2

);fputs

(buffer

,stdout

);va_end(vl

);}

李遲 2015.4.23 周四 中午

乙個用於傳遞可變引數的巨集

早上開啟郵箱,在訂閱的郵件列表裡發現了乙個關於可變引數的討論,剛好前幾天用過它,於是進去看了看,獲益匪淺。收集整理如下,以備中文引擎查詢。原討論位址如下 http groups.google.com group comp.lang.c browse thread thread f18fb0c3947...

C 帶引數執行緒的乙個簡單示例

using system using system.collections.generic using system.componentmodel using system.data using system.drawing using system.text using system.window...

xml的乙個示例

function.h cstring openfile cstring cstring getcontext cstring,int,int void str2array cstring struct xmlnode function.cpp include include include incl...