GCC有一个很好的特性__attribute__,能够告知编译器某个声明的属性,从而在编译阶段检查引用该符号的地方调用方式是否符合其属性,从而产生警告信息,让错误尽早发现。html
attribute format 在printf-like或者scanf-like的函数声明处加入__attribute__((format(printf,m,n)))或者__attribute__((format(scanf,m,n)));表示在编译时对该函数调用位置进行检查。数字m表明format string的是第几个参数,n表明变长参数位于第几个参数。举个直观的例子。shell
<!-- lang: cpp --> // gccattr.c extern void myprintf(const int level, const char *format, ...) __attribute__((format(printf, 2, 3))); // format位于第2个参数,变长参数...位于第3个参数开始 void func() { myprintf(1, "s=%s\n", 5); myprintf(2, "n=%d,%d,%d\n", 1, 2); }
<!-- lang: cpp -->函数
而后用gcc编译这个文件,注意要打开编译告警-Wallcode
<!-- lang: shell --> $ gcc -Wall -c gccattr.c -o gccattr.o gccattr.c: In function ‘func’: gccattr.c:5: warning: format ‘%s’ expects type ‘char *’, but argument 3 has type ‘int’ gccattr.c:7: warning: too few arguments for format
能够看到,编译器根据attribute检查了myprintf函数的参数,因为变长参数类型不正确而出现了告警。这个检查能够避免误用参数致使程序崩溃,例如 myprintf(1, "s=%s\n", 5) 会形成访问无效地址段错误。orm
__attribute__还有其余的声明特性,可用在变量或者类型检查上,更多特性可参考gnu的手册: http://gcc.gnu.org/onlinedocs/gcc-4.0.0/gcc/Function-Attributes.html http://gcc.gnu.org/onlinedocs/gcc-4.0.0/gcc/Variable-Attributes.html http://gcc.gnu.org/onlinedocs/gcc-4.0.0/gcc/Type-Attributes.htmlhtm
http://gcc.gnu.org/onlinedocs/gcc-3.2/gcc/Function-Attributes.html http://gcc.gnu.org/onlinedocs/gcc-3.2/gcc/Variable-Attributes.html http://gcc.gnu.org/onlinedocs/gcc-3.2/gcc/Type-Attributes.htmlget