首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

C语言__attribute__的运用

在阅读内核源码时,常常可以看到类似于这样子的写法:

即,在某一个结构体完成定义后,跟上一个__attribute__(xxx),这是GNU C的一个特色机制,使用__attribute__可以用来设置函数属性、变量属性和类型属性。

__attribute__的书写特征是在attribute前后都有两个下划线且后面紧跟一对括弧,括弧中包含对应的参数:

关键字__attribute__可以对函数、变量、类型(包括结构体struct和共用体union)进行属性设置,在使用__attribute__参数时,可以在参数前后也加上双下划线__,效果是会在相应头文件里使用它而不用关心头文件里是否存在重名宏定义。

常见的attribute参数介绍

aligned

指定对象的对齐格式(字节单位),如:

该声明将强制编译器确保变量类型为Struct S或者int32_t的变量(成员)在分配空间时采用8字节对齐方式。

采用上述格式可以手动指定对齐格式,同样可以采用默认的对齐方式,不指定数字时,编译器将依据目标机器情况使用最大最有益的对齐方式:

在上面的例子中,如果一个short大小为2字节,那么S的大小为6字节。取一个大于等于6的2次方值,则该值为8,编译器会将S类型设置为对齐方式8字节,可以看出aligned属性使被设置的对象占用更多空间

attribute属性效力也受到连接器限制,如果机器最大只支持16字节对齐,设置32并不会有什么用。

下面继续使用一些小例子来观察__attribute__的作用:

对齐在N上的概念是指,某一变量的存放起始地址%N=0,编译器对齐原则:

1.数据类型自身的对齐值:对于char型数据,其自身对齐值为1,对于short型为2,对于int,float,double类型,其自身对齐值为4,单位字节。

2.结构体或者类的自身对齐值是其成员中自身对齐值最大的那个值。

3.指定对齐值:是指使用#pragma pack (value)时的指定对齐值value。

4.数据成员、结构体和类的有效对齐值:自身对齐值和指定对齐值中小的那个值。

关于字节对齐参考:

packed

使用该属性对struct和union类型进行定义,设定其类型的每一个变量的内存约束。要求编译器取消结构在编译过程中的优化对齐(按1字节对齐),是GCC特有语法,只跟编译器有关。

如上面的例子中,packed_struct类型的变量中的成员会紧紧挨在一起,但需要注意其内部unpacked_struct类型的成员变量s的内部不会被pack,如果希望内部成员变量也被packed,对于unpacked_struct也需要使用packed进行约束。

at

at表示绝对定位,可以把变量或函数绝对定位到Flash中,或者定位到RAM。

1)定位到flash中,一般用于固化的信息,如出厂参数,上位机配置参数,ID卡卡号,flash标记等。

2)定位到RAM中,一般用于数据量比较大的缓存,如串口缓存,再就是某个位置的特定变量。

绝对定位不能在函数中定义,局部变量定义在栈区,由MDK(微控制器开发套件)自动分配释放,不能定义为绝对地址,只能在函数外定义;定义长度不能造成堆栈或flash溢出。

section

将作用的函数放入指定段中

format

使用该属性可以给被声明的函数加上类似于printf和scanf的特征,它可以使编译器检查函数声明和函数实际调用参数之间的格式化字符串是否匹配。该功能十分有用,尤其是处理一些很难发现的bug。

format的语法格式为:

需要注意的是,__attribute__并不会为你填充字符串,而是需要使用类似于va_list这样的可变参数列表,或者通过参数地址计算去直接处理参数列表,编译器只是会对传入参数做检查,并在启用-Wall选项时输出参数不正确的警告信息。

noreturn

该参数告诉编译器某个函数从不返回值,观察这个例子:

pure和const

用pure属性修饰的函数用来说明该函数除了返回值之外没有其他任何 效果,并且该函数所返回的值仅仅依赖于函数的形参以及/或全局对象。用 pure属性所修饰的函数可以用来辅助编译器做消除公共子表达式以及帮助 做循环优化,使用这种函数就好比使用算术操作符一般。对同一个使用pure属性修饰的函数连续做两次调用(如果该函数带有参 数,那么两次调用应该用同样的实参),那么这两次调用所返回的结果应 该始终是相同的。const比pure更严格,它要求函数不能读全局对象,此外用const修饰的函数参数不能为指针类型,在const函数内部不能调用非const函数。

always_inline、noinline和flatten

分别为强制优化为内联函数、声明为非内联函数和尽可能做内联处理。

sentinel

提醒程序员此可变参数函数需要一个NULL作为最后一个参数。

used和unused

used告诉编译器避免被连接器因为未被使用而优化掉,unused作用是即使没有使用这个函数,编译器也不警告。

visibility(“visibility_type”)

可见性设置

default

default 可见性是默认的符号链接可见性,如果我们不指定visibility 属性,那么默认就使用默认的可见性。默认可见性的对象与函数可以直接在其他模块中引用,包括在动态链接库中 ,它属于一个正常,完整的外部连接。

hidden

该符号不存放在动态符号表中,因此,其他可执行文件或共享库都无法直接引用它。使用函数指针可进行间接引用。

internal

除非由 特定于处理器的应用二进制接口 (psABI) 指定,否则,内部可见性意味着不允许从另一模块调用该函数。

protected

该符号存放在动态符号表中,但定义模块内的引用将与局部符号绑定。也就是说,另一模块无法覆盖该符号。

weak和weakref

weak声明某一个全局符号为弱符号,当出现重名的时候不引发重定义错误,直接忽略它。weakref为弱引用,功能类似。

可见,__attribute__与编译器密切相关,主要用于编译优化的场景,因为参数实在很多,还有更多的参数并没有再继续列举。

参考:

https://www.cnblogs.com/embedded-linux/p/5801999.html

官网介绍:

GCC 4.0

GCC 4.0 Function Attributes

https://gcc.gnu.org/onlinedocs/gcc-4.0.0/gcc/Function-Attributes.html

GCC 4.0 Variable Attributes

https://gcc.gnu.org/onlinedocs/gcc-4.0.0/gcc/Variable-Attributes.html

GCC 4.0 Type Attributes

https://gcc.gnu.org/onlinedocs/gcc-4.0.0/gcc/Type-Attributes.html

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20230607A03T1B00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券