概述
1 解释
format
是GCC提供的众多attribute之一,这个attribute的作用是告知编译器检查传给相应函数的参数中的格式字符串:
/* 这是用在声明的情况,用在定义也可以 */
/* 一般全局函数用在声明,这样包含相应头文件并使用该全局函数的源码就会被编译器做相应检查 */
/* 而局部函数就在本文件使用,无需声明,那么这个attribute可以直接用在定义 */
extern int
my_printf(void *my_object, const char *my_format, ...)
__attribute__ ((format(archetype, string-index, first-to-check)));
在这个例子中也就是检查my_format
参数。
熟悉c语言的同学应该知道,像printf
等函数使用时,有格式字符串参数。格式字符串中使用诸如%d
、%c
这样的格式控制字符来进行指出后续参数的类型以及格式。但是格式控制字符并不是随意指定的,比如printf中%b
、%j
就是不存在的。此外,也不能出现指定了%d
,但后面的变参部分却没有传整形参数或传的是其它类型的参数。换句话说,格式字符串是有一定要求的。而且,不同的用到格式字符串的函数对于格式字符串的要求也是不同的,比如strftime
函数,该函数的格式字符串中就有%b
,表示月份的简写。
假如我想要上例中的my_printf
的格式字符串应该和printf的格式字符串风格一致,并希望编译器对此做检查,那么就可以这样使用format属性:
extern int
my_printf(void *my_object, const char *my_format, ...)
__attribute__ ((format(printf, 2, 3)));
现在解释一下archetype
、string-index
、first-to-check
的含义:
名称 | 含义 |
---|---|
archetype | 检查格式字符串参数和archetype指定的函数的格式字符串风格是否一致 |
string-index | 要检查的格式字符串参数在函数原型中的位置(第几个参数),从1开始算 |
first-to-check | 根据格式字符串去检查的第一个参数的位置,通常就是变参的位置 |
仍以strftime函数来说,这个函数没有变参部分,像这种或类似的情况,那么first-to-check
应该指定为0。此时,编译器仅检查格式字符串的风格,而不会检查变参部分的类型是否相匹配。
2 举例
在linux kernel中就使用到了这个attribute,比如说下面的宏定义:
#define __printf(a, b) __attribute__((__format__(printf, a, b)))
在kobject.h
中,有这样的函数声明:
extern __printf(2, 3)
int kobject_set_name(struct kobject *kobj, const char *name, ...);
extern __printf(2, 0)
int kobject_set_name_vargs(struct kobject *kobj, const char *fmt,
va_list vargs);
使用format属性可以让编译器多做一些检查,以免我们编程时犯错误。如果一些本来难以察觉的错误能够通过一个属性的使用,使得编译器帮我们检查出来,那么,这对项目的开发是很有益的。
最后
以上就是无限黄豆为你收集整理的GCC的attribute——format1 解释2 举例的全部内容,希望文章能够帮你解决GCC的attribute——format1 解释2 举例所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复