2022年C语言中的__attribute__机制 .pdf
《2022年C语言中的__attribute__机制 .pdf》由会员分享,可在线阅读,更多相关《2022年C语言中的__attribute__机制 .pdf(9页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、C 语言中的 _attribute_机制分类: C/C+ 2011-10-24 19:53100人阅读 评论 (0)收藏举报c 语言 attributesprofiling编译器 structGNU C 的一大特色(却不被初学者所知)就是_attribute_ 机制。 _attribute_ 可以设置函数属性(Function Attribute) 、 变量属性(Variable Attribute) 和类型属性(Type Attribute ) 。_attribute_ 书写特征是: _attribute_ 前后都有两个下划线,并切后面会紧跟一对原括弧,括弧里面是相应的_attribute_
2、 参数。_attribute_ 语法格式为:_attribute_ (attribute-list) 其位置约束为:放于声明的尾部“ ;” 之前。函数属性( Function Attribute)函数属性可以帮助开发者把一些特性添加到函数声明中,从而可以使编译器在错误检查方面的功能更强大。_attribute_ 机制也很容易同非GNU 应用程序做到兼容之功效。GNU CC 需要使用 Wall 编译器来击活该功能,这是控制警告信息的一个很好的方式。下面介绍几个常见的属性参数。_attribute_ format 该_attribute_ 属性可以给被声明的函数加上类似printf 或者 scan
3、f 的特征,它可以使编译器检查函数声明和函数实际调用参数之间的格式化字符串是否匹配。该功能十分有用, 尤其是处理一些很难发现的bug。format 的语法格式为:format (archetype, string-index, first-to-check) format 属性告诉编译器,按照printf, scanf, strftime 或 strfmon 的参数表格式规则对该函数的参数进行检查。“archetype ”指定是哪种风格; “string -index ” 指定传入函数的第几个参数是格式化字符串;“first -to-check” 指定从函数的第几个参数开始按上述规则进行检查。
4、具体使用格式如下:_attribute_(format(printf,m,n) _attribute_(format(scanf,m,n) 其中参数 m 与 n 的含义为:m:第几个参数为格式化字符串(format string );n:参数集合中的第一个,即参数“”里的第一个参数在函数参数总数排在第几,注意,有时函数参数里还有“ 隐身 ” 的呢,后面会提到;名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 1 页,共 9 页 - - - - - - - - - 在使用上, _attr
5、ibute_(format(printf,m,n)是常用的,而另一种却很少见到。下面举例说明,其中 myprint 为自己定义的一个带有可变参数的函数,其功能类似于printf :/m=1 ;n=2 extern void myprint(const char *format,.) _attribute_(format(printf,1,2); /m=2 ;n=3 extern void myprint(int l,const char *format,.) _attribute_(format(printf,2,3); 需要特别注意的是,如果myprint 是一个函数的成员函数,那么m 和
6、n 的值可有点 “ 悬乎”了,例如:/m=3 ;n=4 extern void myprint(int l,const char *format,.) _attribute_(format(printf,3,4); 其原因是, 类成员函数的第一个参数实际上一个“ 隐身 ” 的“this ”指针。(有点 C+ 基础的都知道点 this 指针,不知道你在这里还知道吗?)这里给出测试用例:attribute.c ,代码如下:1:2:extern void myprint(const char *format,.) _attribute_(format(printf,1,2); 3:4:void te
7、st() 5: 6: myprint(i=%dn,6); 7: myprint(i=%sn,6); 8: myprint(i=%sn,abc); 9: myprint(%s,%d,%dn,1,2); 10: 运行 $gcc Wall c attribute.c attribute后,输出结果为:attribute.c: In function test: attribute.c:7: warning: format argument is not a pointer (arg 2) attribute.c:9: warning: format argument is not a pointer
8、 (arg 2) attribute.c:9: warning: too few arguments for format 如果在 attribute.c中的函数声明去掉_attribute_(format(printf,1,2),再重新编译,既运行$gcc Wall c attribute.c attribute后,则并不会输出任何警告信息。注意,默认情况下,编译器是能识别类似printf 的“ 标准 ” 库函数。_attribute_ noreturn 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - -
9、 - - - - 第 2 页,共 9 页 - - - - - - - - - 该属性通知编译器函数从不返回值,当遇到类似函数需要返回值而却不可能运行到返回值处就已经退出来的情况,该属性可以避免出现错误信息。C 库函数中的abort ()和 exit ()的声明格式就采用了这种格式,如下所示:extern void exit(int) _attribute_(noreturn);extern void abort(void) _attribute_(noreturn); 为了方便理解,大家可以参考如下的例子:/name: noreturn.c ;测试 _attribute_(noreturn)
10、extern void myexit(); int test(int n) if ( n 0 ) myexit(); /* 程序不可能到达这里*/ else return 0; 编译显示的输出信息为:$gcc Wall c noreturn.c noreturn.c: In function test: noreturn.c:12: warning: control reaches end of non-void function 警告信息也很好理解,因为你定义了一个有返回值的函数test 却有可能没有返回值,程序当然不知道怎么办了!加上 _attribute_(noreturn)则可以很好的
11、处理类似这种问题。把extern void myexit();修改为:extern void myexit() _attribute_(noreturn);之后,编译不会再出现警告信息。_attribute_ const 该属性只能用于带有数值类型参数的函数上。当重复调用带有数值参数的函数时,由于返回值是相同的, 所以此时编译器可以进行优化处理,除第一次需要运算外,其它只需要返回第一次的结果就可以了,进而可以提高效率。该属性主要适用于没有静态状态(static state)和副作用的一些函数,并且返回值仅仅依赖输入的参数。为了说明问题, 下面举个非常 “ 糟糕 ” 的例子, 该例子将重复调用一
12、个带有相同参数值的函数,具体如下:extern int square(int n) _attribute_ (const);. for (i = 0; i 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 3 页,共 9 页 - - - - - - - - - total += square (5) + i; 通过添加 _attribute_(const)声明,编译器只调用了函数一次,以后只是直接得到了相同的一个返回值。事实上, const 参数不能用在带有指针类型参数的函数中,因为该
13、属性不但影响函数的参数值,同样也影响到了参数指向的数据,它可能会对代码本身产生严重甚至是不可恢复的严重后果。并且,带有该属性的函数不能有任何副作用或者是静态的状态,所以,类似getchar ()或time()的函数是不适合使用该属性的。-finstrument-functions 该参数可以使程序在编译时,在函数的入口和出口处生成instrumentation调用。恰好在函数入口之后并恰好在函数出口之前,将使用当前函数的地址和调用地址来调用下面的profiling 函数。(在一些平台上, _builtin_return_address不能在超过当前函数范围之外正常工作,所以调用地址信息可能对p
14、rofiling 函数是无效的。)void _cyg_profile_func_enter(void *this_fn, void *call_site); void _cyg_profile_func_exit(void *this_fn, void *call_site); 其中,第一个参数this_fn 是当前函数的起始地址,可在符号表中找到;第二个参数call_site是指调用处地址。instrumentation 也可用于在其它函数中展开的内联函数。从概念上来说,profiling 调用将指出在哪里进入和退出内联函数。 这就意味着这种函数必须具有可寻址形式。如果函数包含内联,而所有使
15、用到该函数的程序都要把该内联展开,这会额外地增加代码长度。如果要在C 代码中使用extern inline声明,必须提供这种函数的可寻址形式。可对函数指定no_instrument_function属性, 在这种情况下不会进行Instrumentation操作。例如,可以在以下情况下使用no_instrument_function属性: 上面列出的profiling 函数、高优先级的中断例程以及任何不能保证profiling 正常调用的函数。no_instrument_function 如果使用了 -finstrument-functions ,将在绝大多数用户编译的函数的入口和出口点调用pr
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 2022年C语言中的_attribute_机制 2022 语言 中的 _attribute_ 机制
限制150内