最近,在看libevent源碼,第一次看到__attribute__((format(printf, a, b)))這種寫法。因此,在這里記錄下用法。
功能:__attribute__ format屬性可以給被聲明的函數加上類似printf或者scanf的特征,它可以使編譯器檢查函數聲明和函數實際調用參數之間的格式化字符串是否匹配。format屬性告訴編譯器,按照printf, scanf等標准C函數參數格式規則對該函數的參數進行檢查。這在我們自己封裝調試信息的接口時非常的有用。
format的語法格式為:
format (archetype, string-index, first-to-check)
其中,“archetype”指定是哪種風格;“string-index”指定傳入函數的第幾個參數是格式化字符串;“first-to-check”指定從函數的第幾個參數開始按上述規則進行檢查。
具體的使用如下所示:
__attribute__((format(printf, a, b)))
__attribute__((format(scanf, a, b)))
其中參數m與n的含義為:
a:第幾個參數為格式化字符串(format string);
b:參數集合中的第一個,即參數“…”里的第一個參數在函數參數總數排在第幾。
下面直接給個例子來說明:
#include <stdio.h>
#include <stdarg.h>
#if 1
#define CHECK_FMT(a, b) __attribute__((format(printf, a, b)))
#else
#define CHECK_FMT(a, b)
#endif
void TRACE(const char *fmt, ...) CHECK_FMT(1, 2);
void TRACE(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
(void)printf(fmt, ap);
va_end(ap);
}
int main(void)
{
TRACE("iValue = %d\n", 6);
TRACE("iValue = %d\n", "test");
return 0;
}
注意:需要打開警告信息即(-Wall)。
編譯結果如下所示:
main.cpp: In function ‘int main()’:
main.cpp:26:31: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘const char*’ [-Wformat=]
TRACE("iValue = %d\n", "test");
如果不使用__attribute__ format則不會有警告。