嵌入式开发,离不开 C 语言,C语言中有很多语法会直接或间接影响你代码的质量,下面就来讲讲__attribute__ 关键字的用法 。
1. 什么是 __attribute__GNU C 编译器增加了一个 __attribute__ 关键字用来声明一个函数、变量或类型的特殊属性 。申明这些属性主要用途就是指导编译程序进行特定方面的优化或代码检查 。
__attrabute__ 的用法非常简单,当我们定义一个一个函数、变量或者类型时,直接在他名字旁边添加如下属性即可:
__attribute__ ((ATTRIBUTE))
需要注意的是,__attribute__ 后面是两对小括号,不能图方便只写一对,否则会编译报错 。括号里的 ATTRIUBTE 表示要声明的属性,目前支持十几种属性声明:
- section:自定义段
- aligned:对齐
- packed:对齐
- format:检查函数变参格式
- weak:弱声明
- alias:函数起别名
- noinline:无内联
- always_inline:内联函数总是展开
- ......
char c __attribute__((algined(8))) = 4;int global_val __attribute__ ((section(".data")));
当然,我们对一个变量也可以同时添加多个属性 。在定义变量前,各个属性之间用逗号隔开 。以下三种声明方式是没有问题的 。char c__attribute__((packed, algined(4)));char c__attribute__((packed, algined(4))) = 4;__attribute__((packed, algined(4))) char c = 4;
2. 属性声明:sectionsection 属性的主要作用是:在程序编译时,将一个函数或者变量放到指定的段,即指定的section 中 。一个可执行文件注意由代码段,数据段、BSS 段构成 。代码段主要用来存放编译生成的可执行指令代码、数据段和BSS段用来存放全局变量和未初始化的全局变量 。
除了这三个段,可执行文件还包含一些其他的段 。我们可以用 readelf 去查看一个可执行文件各个section信息 。
下表是不同的 section 及说明:
section组成代码段(.text)函数定义、程序语句数据段 (.data)初始化的全局变量、初始化的静态局部变量BSS 段(.bss)未初始化的全局变量,未初始化的静态局部变量
int global_val = 8;int unint_val;int main(void){return 0;}
我们使用gcc 编译这个程序:gcc -m32 -o a.out gnu.c
查看符表号信息:#readelf -s a.outNum:ValueSize TypeBindVisNdx Name44:0804c0204OBJECTGLOBAL DEFAULT24 unint_val45:080490904FUNCGLOBAL HIDDEN13 __x86.get_pc_thunk.bx46:0804c0100NOTYPEWEAKDEFAULT23 data_start47:0804c01c0NOTYPEGLOBAL DEFAULT23 _edata48:080491c40FUNCGLOBAL HIDDEN14 _fini49:0804c0184OBJECTGLOBAL DEFAULT23 global_val50:0804c0100NOTYPEGLOBAL DEFAULT23 __data_start51:000000000NOTYPEWEAKDEFAULTUND __gmon_start__52:0804c0140OBJECTGLOBAL HIDDEN23 __dso_handle53:0804a0044OBJECTGLOBAL DEFAULT15 _IO_stdin_used54:000000000FUNCGLOBAL DEFAULTUND __libc_start_main@@GLIBC_55:0804916085 FUNCGLOBAL DEFAULT13 __libc_csu_init56:0804c0240NOTYPEGLOBAL DEFAULT24 _end57:080490801FUNCGLOBAL HIDDEN13 _dl_relocate_static_pie58:0804904055 FUNCGLOBAL DEFAULT13 _start59:0804a0004OBJECTGLOBAL DEFAULT15 _fp_hw60:0804c01c0NOTYPEGLOBAL DEFAULT24 __bss_start61:0804915210 FUNCGLOBAL DEFAULT13 main
查看 section 信息:# readelf -S a.out
文章插图
使用 __attribute__ ((section("xxx"))),修改段的属性 。
int global_val = 0;int unint_val __attribute__((section(".data")));int main(){return 0;}
可以看到 unint_val 这个变量,已经被编译器放在数据段中 。当然也可以自定义段的名称 。文章插图
3. 属性声明:alignedGNU C 通过 __attribute__ 来声明 aligned 和 packed 属性,指定一个变量或类型的对齐方式 。
通过 aligned 属性,我们可以显示地指定变量 a 在内存中的地址对齐方式 。aligned 有一个参数,表示要按几个字节对齐,使用时要注意,地址对齐的字节数必须是 2 的幂次方,否则编译就会报错 。
3.1 地址对齐
#include <stdio.h>int a = 1;int b = 2;char c1 = 3;char c2 = 4;int main(){printf("a = %pn", &a);printf("b = %pn", &b);printf("c1 = %pn", &c1);printf("c2 = %pn", &c2);return 0;}
可以看到,char 占一个字节,c2的地址紧挨着 c1a = 0x404030b = 0x404034c1 = 0x404038c2 = 0x404039
使用 aligned 地址对齐#include <stdio.h>int a = 1;int b = 2;char c1 = 3;char c2 __attribute__((aligned(4))) = 4;int main(){printf("a = %pn", &a);printf("b = %pn", &b);printf("c1 = %pn", &c1);printf("c2 = %pn", &c2);return 0;}
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- win10更新失败报0x800f081f错误代码怎么办
- 能够体现阴阳相对属性的是,能够体现事物阴阳相对属性的是什么-
- steam错误代码118解决方法
- 十二星座的五行属性
- 葡萄属性热还是寒
- 电脑开机蓝屏,代码stop:0x00000024解决方法
- win10专业版中我的电脑及系统属性哪去了
- 谢谢你医生|杨幂《谢谢你医生》再获央视预热,阵容雄厚,爆款属性明显,要火
- 侠盗飞车代码版本?侠盗猎车手5的作弊码输入方法和作弊码?
- 西洋参性味_西洋参属性