GNU C编译器扩展关键字__attribute__
GNU C增加了一个__attribute__关键字用来声明一个函数、变量或者类型的特殊属性,声明这个特殊属性有什么用呢?主要用途指导编译器在编译程序时进行特定的优化或者代码检查,例如,我们可以通过属性声明来指定某个变量或者数据的对齐方式
__attribute__的使用非常简单,当我们定义一个函数,变量或者类型时,直接在他们的旁边添加下面的属性 声明即可。
__atribute__((ATTRIBTE))
注意,__attribute__后面是两对小括号,不能图方便只写一对,否则编译报错。括号里面的ATTRIBUTE表示要声明的属性,目前__attribute__支持十几种属性声明
- section:在程序编译时,将一个函数或者变量放到指定的段,即指定的section中。一个可执行文件主要由代码段,数据段、BSS 段构成。
- aligned:GNU C 通过__atttribute__来声明aligned和packed属性,指定一个变量或类型的对齐方式。这两个属性用来告诉编译器:在给变量分配存储空间时,要按指定的地址对齐方式给变量分配地址。如果想定义一个变量,在内存中以8字节地址对齐,就可以这样定义。
- packed:告诉编译器取消结构在编译过程当中的优化对齐,按照实际占用字节数进行对齐,是 GCC 特有的语法。
- format:这是字符串,包含了要被写入到字符串str的文本。它可以包含嵌入的format标签,format标签可被随后的附加参数中指定的值替换,并按需求进行格式化。
- weak:如果这个关键字用在函数定义上面,一般情况下和一般函数没有两样。被WEAK或__weak声明的函数, 可以在自己的文件中重新定义一个同名函数,最终编译器编译的时候,会选择定义的函数,如果没有重新定义这个函数,那么编译器就会执行WEAK或__weak声明的函数,并且编译器不会报错。
- alias:这是一个别名,是一种类型别名声明,可以用来给类型取别名,这样就可以用更简洁的方式来引用一个类型,增强代码的可读性。
- noinline:noinline是一个内联函数的声明,告诉编译器这个函数不应该被内联。当编译器遇到一个函数调用时,它会尝试将这个调用替换为函数的代码本身,这被称为内联函数。如果函数被声明为noinline,那么编译器就不会进行这个替换,而是会生成一个调用该函数的指令。
- always_inline:always_inline是一个内联函数的声明,告诉编译器这个函数应该被内联。当编译器遇到一个函数调用时,它会尝试将这个调用替换为函数的代码本身,这被称为内联函数。如果函数被声明为always_inline,那么编译器就会进行这个替换,而不仅仅是在某些情况下。
这里的weak感觉很管用,写C代码,经常会遇到自己写的代码重复定义的问题,有了这个可以避开一些此类链接错误。
使用示例:
char c2 __attribute__((aligned(8)) = 4;
int global_val_attribute__((section(".data")))
char c2 __attribute__((packed,aligned(4)));
char c2 __attribute__((packed,aligned(4))) = 4;
__attribute_((packed, aligned(4))) char c2 = 4;
char c2 = 4 __attribute__((packed, aligned(4)));
编译后的那些段
.interp
.note
.note
.gnu
.dynsym
.dynstr
.gnu.version
.gnu.version_r
.rel.dyn
.rel.plt
.init
.plt.got
.text
.fini
.rodata
.eh_frame_hdr
.eh_frame
.init_array
.fini_array
.jcr
.dynamic
.got
.got.plt
.data
.bss
.comment
.shstrab
.symtag
.strtab