From:https://blog.csdn.net/shift_wwx/article/details/103689854
__attribute 语法的来源
GNU C 的一大特色就是__attribute__ 机制。attribute 可以设置函数属性(Function Attribute)、变量属性(Variable Attribute)和类型属性(Type Attribute)。
其位置约束为: 放于声明的尾部“;” 之前
attribute 书写特征为: attribute 前后都有两个下划线,并切后面会紧跟一对原括弧,括弧里面是相应的__attribute__ 参数。
attribute 语法格式为: attribute ((attribute-list))
当__attribute__ 用于修饰对象时,它就如同C 语言语法体系结构的类型限定符,跟const , volatile , restrict 等属一类。
当__attribute__ 用于修饰函数时,它就相当于一个函数说明符,跟inline,Noreturn 属同一类。
当__attribute_ 用于修饰一个结构体,联合体或者枚举类型,该限定符只能放在类型标识符之前。
__attribute 所支持的类型
当我们需要识别当前编译器能否支持GNU 语法拓展,我们可以使用 __GNU __ 宏作为区分
常用函数属性
attribute((Noreturn))
表示没有返回值
这个属性告诉编译器函数不会返回,这可以用来抑制关于未达到代码路径的错误。 C库函数abort()和exit()都使用此属性声明:
attribute((always_inline))
对于声明为内联的函数,会强制优化。所有加了attribute((always_inline))的函数再被调用时不会被编译成函数调用而是直接扩展到调用函数体内。
attribute((noinline))
与上面的相反,声明为非内联函数
attribute((flatten))
用此修饰的函数,在函数中调用的每一个函数都将尽可能地做内联处理。而用flatten 属性修饰的函数,是否内联处理,就要根据编译器当前的编译选项以及当前上下文来定。
attribute((pure))
用pure属性修饰的函数用来说明该函数除了返回值之外没有其他任何 效果,并且该函数所返回的值仅仅依赖于函数的形参以及/或全局对象。用 pure属性所修饰的函数可以用来辅助编译器做消除公共子表达式以及帮助 做循环优化,使用这种函数就好比使用算术操作符一般。
用pure属性所修饰的函数体内不应该含有无限循环,不应该对volatile 修饰的全局对象进行访问或是对多个线程所共享的全局对象进行访问,也 不应该访问其他系统资源,比如对文件、套接字等进行操作。简而言之, 对同一个使用pure属性修饰的函数连续做两次调用(如果该函数带有参 数,那么两次调用应该用同样的实参),那么这两次调用所返回的结果应 该始终是相同的。因此,用pure属性所修饰的函数也很容易让编译器做内联处理。
attribute((const))
用const属性修饰的函数与用pure属性修饰的十分类似,不过const属性比pure更严格,它要求函数不能读全局对象。此外,用const属性修饰的函数的参数不能是一个指针类型,而且在用const属性修饰的函数内往往不能调用一个非const属性的函数。
attribute((sentinel))
提醒程序员“此可变参数函数需要一个NULL作为最后一个参数。
attribute((format))
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)))
其中参数a与b的含义为:
a:第几个参数为格式化字符串(format string);
b:参数集合中的第一个,即参数“…”里的第一个参数在函数参数总数排在第几。
attribute((section(“name”)))
将作用的函数或数据放入指定名为"section_name"对应的段中
static void __attribute((section("__TEXT,MySection" ))) myFun1(void) {
print("");
}
attribute((unused))
即使没有使用这个函数,编译器也不警告
attribute((used))
告诉编译器避免被链接器因为未用过而被优化掉。
attribute((visibility(“visibility_type”)))
visibility_type 类型有4种:
default
default 可见性是默认的符号链接可见性,如果我们不指定visibility 属性,那么默认就使用默认的可见性。默认可见性的对象与函数可以直接在其他模块中引用,包括在动态链接库中 ,它属于一个正常,完整的外部连接。
hidden
该符号不存放在动态符号表中,因此,其他可执行文件或共享库都无法直接引用它。使用函数指针可进行间接引用。
internal
除非由 特定于处理器的应用二进制接口 (psABI) 指定,否则,内部可见性意味着不允许从另一模块调用该函数。
protected
该符号存放在动态符号表中,但定义模块内的引用将与局部符号绑定。也就是说,另一模块无法覆盖该符号。
attribute((weak))
若两个或两个以上全局符号(函数或变量名)名字一样,而其中之一声明为weak symbol(弱符号),则这些全局符号不会引发重定义错误。链接器会忽略弱符号,去使用普通的全局符号来解析所有对这些符号的引用,但当普通的全局符号不可用时,链接器会使用弱符号。当有函数或变量名可能被用户覆盖时,该函数或变量名可以声明为一个弱符号。弱符号也称为weak alias(弱别名)。
attribute((weakref(“target”)))
请注意引用与定义的区别。weakref就是申明某个引用为弱引用,弱引用时如果需引用符号不存在也不会链接出错,而是将需要引用的符号定义为WEAK属性及0地址(跟前面的WEAK属性很相似吧)。
weakref的用法有点特别,必须要配合alias使用及必须是static定义。attribute((weak(“target”)))相当于
__attribute__((weakref,alias(“target”)))
attribute((malloc))
由如此标记的函数返回的块不得包含任何指向其他对象的指针.目的是帮助编译器估计哪些指针可能指向同一个对象:该属性告诉GCC它不必担心你的函数返回的对象可能包含指向它正在跟踪的其他东西的指针。
attribute((aligned))
aligned 属性修饰一个函数时,用于直至该函数的首地址至少需要 aligned 个字节对齐。