特殊属性(__attribute__)

来源:互联网 发布:淘宝上买港版iphone6s 编辑:程序博客网 时间:2024/04/29 00:05

GCC 允许声明函数、变量和类型的特殊属性,以便指示编译器进行特定方面的优化和更仔细的代码检查。使用方式为在声明后加上:
__attribute__ (( ATTRIBUTE ))
其中 ATTRIBUTE 是属性的说明,多个说明之间以逗号分隔。GCC 可以支持十几个属性,下面介绍一

些比较常用的。


noreturn
属性 noreturn 用于函数,表示该函数从不返回。它能够让编译器生成较为优化的代码,消除不必要的

警告信息。


format(archetype, string-index, first-to-check)
属性 format 用于函数,表示该函数使用 printf、scanf、strftime 或 strfmon 风格的参数,并可以让编译
器检查函数声明和函数实际调用参数之间的格式化字符串是否匹配。
archetype 指定是哪种风格,string-index 指定传入函数的第几个参数是格式化字符串,first-to-check 指
定从函数的第几个参数开始按照上述规则进行检查。比如:
++++ include/linux/kernel.h164 static inline int printk(const char *s, ...)165__attribute__ ((format (printf, 1, 2)));
表示 printk 的第一个参数是格式化字符串,从第二个参数开始根据格式化字符串检查参数。




unused

属性 unused 用于函数和变量,表示该函数或变量可能并不使用,这个属性能够避免编译器产生警告信息。

section ("section-name")
属性 section 用于函数和变量,比如:

++++ include/linux/init.h43 #define __init __attribute__ ((__section__ (".init.text"))) __cold44 #define __initdata __attribute__ ((__section__ (".init.data")))45 #define __exitdata __attribute__ ((__section__(".exit.data")))46 #define __exit_call __attribute_used____attribute__((__section__(".exitcall.exit")))

通常编译器将函数放在.text 节,变量放在.data 或.bss 节,而使用 section 属性,可以让编译器将函数或
变量放在指定的节中。因此上面对__init 的定义便表示将__init 修饰的代码放在.init.text 节。

连接器可以把相同节的代码或数据安排在一起,Linux 内核很喜欢使用这种技术,比如__init 修饰的
所有代码都会被放在.init.text 节里,初始化结束后就可以释放这部分内存

aligned (ALIGNMENT)

属性 aligned 用于变量、结构或联合,设定一个指定大小的对齐格式,以字节为单位,
比如:
++++ drivers/usb/host/ohci.h181 struct ohci_hcca {182 #define NUM_INTS 32183__hc32int_table [NUM_INTS];/* periodic schedule */184185 /*186 * OHCI defines u16 frame_no, followed by u16 zero pad.187 * Since some processors can't do 16 bit bus accesses,188 * portable access must be a 32 bits wide.189 */190 __hc32 frame_no; /* current frame number */191 __hc32 done_head; /* info returned for an interrupt */192 u8 reserved_for_hc [116];193 u8 what [4];/* spec only identifies 252 bytes :) */194 } __attribute__ ((aligned(256)));

表示结构体 ohci_hcca 的成员以 256 字节对齐。
如果 aligned 后面不紧跟一个指定的数字值,那么编译器将依据目标机器情况使用最大、最有益的对
齐方式。
需要注意的是,attribute 属性的效果与你的连接器也有关,如果你的连接器最大只支持 16 字节对齐,
那么此时定义 32 字节对齐也是无济于事的。

packed

(简单来说就是不填充字节,严格按照定义分配地址。因为有些接口协议需要严格按照一定的格式去操作,如果被系统自动填充了多余的位,可能会产生意外的影响)

属性 packed 用于变量和类型,用于变量或结构体成员时表示使用最小可能的对齐,用于枚举、结构体
或联合类型时表示该类型使用最小的内存。
属性 packed 多用于定义硬件相关的结构时,使元素之间不会因对齐产生问题。比如:

++++ include/asm-i386/desc.h295 struct usb_interface_descriptor {296 __u8 bLength;297 __u8 bDescriptorType;298299 __u8 bInterfaceNumber;300 __u8 bAlternateSetting;301 __u8 bNumEndpoints;302 __u8 bInterfaceClass;303 __u8 bInterfaceSubClass;304 __u8 bInterfaceProtocol;305 __u8 iInterface;306 } __attribute__ ((packed));

其中__attribute__ ((packed))告诉编译器,usb_interface_descriptor 的元素为 1 字节对齐,不要再添加填
充位。
因为这个结构的定义和 usb spec 里是完全一致的,
包括各个字段的长度,
如果不给编译器这个暗示,
编译器就会依据平台的类型在结构的每个元素之间添加一定的填充位,使用这个结构时就不能达到预期的
结果。






0 0
原创粉丝点击