嵌入式C中__attribute__编译属性说明

2023-11-04

锲而不舍,金石可镂

前言

__attribute__是GNU C扩展下一大特性机制,用于设置函数属性(Function Attribute )、变量属性(Variable Attribute )和类型属性(Type Attribute )。
__attribute__前后以两个 _ 标识,后端跟 () 说明跟随参数属性。语法格式为:

_ attribute _ (( ATTRIBUTE ))

其中ATTRIBUTE是属性的说明,多个说明之间以逗号分隔。GCC目前可以支持是几个属性,下面介绍常用属性设置。


参数介绍

1、aligned

aligned用于变量、结构或联合,设定一个指定大小的对齐格式,以字节为单位(参数有效值为2的幂值),比如:

struct _array_
{
    char  flag;
    int   state;
    int length;
}__attribute__((aligned(8)));

struct _array_ array_zero;
int main(void)
{
    printf("This struct size is %d\r\n",sizeof(array_zero));
}

输出结果

This struct size is 16

需要注意的是aligned属性使编译器尽其所能的确保在分配变量空间时,为其设置8字节对齐大小。如果属性后不跟指定数字,编译器将依据你的目标机器情况使用最大最有益的对齐方式。

struct _array_
{
    char  array;
    int   flag;
}__attribute__((aligned(2)));

struct _array_ array_zero;
int main(void)
{
    printf("This struct size is %d\r\n",sizeof(array_zero));
}

如上代码,指定对其方式2字节对齐。结构体对齐则为4字节对齐,则实际对齐方式为4字节对齐,编译输出如下:

This struct size is 8

需要注意的是,attribute 属性的效力与你的连接器也有关,如果你的连接器最大只支持16 字节对齐,那么你此时定义32 字节对齐也是无济于事的。


2、packed

属性packed用于变量和类型,用于变量或结构体成员时表示使用最小可能的对齐,用于枚举、结构体或联合类型时表示该类型使用最小的内存。同属性aligned指引字节对齐时,刚好相反。参照aligned代码测试,编写如下测试代码

struct _array_
{
    char  array;
    int   falg;
}__attribute__((packed));

struct _array_ array_zero;
int main(void)
{
    printf("This struct size is %d\r\n",sizeof(array_zero));
}

结构体类型 arraypacked属性修饰后取消字节对齐,成员变量按1字节大小对齐。编译输出如下:

This struct size is 5

其属性作用效果类似于 #pragma pack(1),需要注意的是packed仅对修饰对象起作用,对内嵌结构体不生效。如下所示:

struct  S{
    char eox;
    int  length;
};

struct _array_
{
    char  array;
    int   falg;
    struct S  _S_;
}__attribute__((packed));

struct _array_ array_zero;
int main(void)
{
    printf("This struct size is %d\r\n",sizeof(array_zero));
}

代码中结构体类型 arraypacked属性修饰,成员变量按1字节对齐。但结构体 S 未被修饰,仍按4字节对齐。编译输出如下:

This struct size is 13


3、at

用来设置变量的绝对地址,指定某个变量处于RAM或 FLASH 里面的某个给定的地址,语法为__attribute__((at(addr)))。
1)、定位到flash中,一般用于固化的信息,如出厂设置的参数,上位机配置的参数,ID卡的ID号,flash标记等等
2)、定位到RAM中,一般用于数据量比较大的缓存,如串口的接收缓存,再就是某个位置的特定变量

const uint8_t array[] __attribute__((at(0x08002800)))={0xA5,0x5A};//定位至flash中,地址为0X08002800
uint8_t RecvBuffer[MAX_RECV_LEN] __attribute__ ((at(0x00025000)));	//接收缓冲,最大MAX_RECV_LEN个字节,起始地址为 0x00025000

以定位至flash为例,工程中添加定义代码。编译查看map文件,Global Symbols类别下,查找到array定义地址信息

array 0x08002800 Data 2 main.o(.ARM.__AT_0x08002800)

或者将编译后的二进制文件使用J-FLASH打开,定位至地址0X8002800,参数值已被写入。
在这里插入图片描述
定位至flash中,需要增加const关键字修饰。另外关于定义使用,需要注意以下两点

1、绝对定位不能在函数中定义,局部变量是定义在栈区的,栈区由MDK自动分配、释放,不能定义为绝对地址,只能放在函数外定义。
2、定义的长度不能超过栈或Flash的大小,否则,造成栈、Flash溢出。


4、section

该属性用于修饰函数或者变量,在编译时将被修饰的变量或是函数编译至特定段中。语法使用__attribute__((section(“xxx”)))

uint8_t ret attribute((section(“.test.”))) = 0;

该段语句意为定义uint8_t类型变量,其初值为0,编译放入".test."的输入段中。工程中添入代码,打开map文件,查找对应信息。

ret 0x200000d0 Data 1 main.o(.test.)

或者修饰函数,也是该属性使用最多的场景。一般与其他属性合并使用,用于Initcall机制中。如:

void func_attribute(void)  __attribute__ ((section(".fun.")));

void func_attribute(void) 
{
    DEBUG_log("This is test\r\n");
}

编译打开map文件,查找对应属性表如下:

func_attribute 0x08000161 Thumb Code 10 main.o(.fun.)


总结

__attribute__支持多属性联合使用,括号内以 ( )做分割。一般常见于操作系统中,大部分第一次接触该扩展属性都是基于Linux下Initcall机制,或者RTT中自动初始化机制(Initcall)。有时间写一篇关于Initcall机制介绍的文章,用作记录。
码字不易,如有错漏,敬请指正。一键三连就更好了!(^ _ ^)!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

嵌入式C中__attribute__编译属性说明 的相关文章

随机推荐

  • 【Rust】用libc实现文件拷贝

    macro export macro rules c string s expr gt use std ffi CString CString new s unwrap as ptr macro export macro rules che
  • office表格标题和表格距离过大怎么解决

    设置 表格 布局 属性 文字环绕 环绕 定位 然后修改成如下 垂直 位置 数据为0厘米
  • 如何使用Hyperledger Fabric和Composer构建区块链网络

    如何使用Hyperledger Fabric和Composer构建区块链网络 这是一个区块链开发入门人员的教程 在开始之前要说明Hyperledger Fabric仅在基于Unix的操作系统上运行 因此 它将无法在Windows上运行 这将
  • (一)云计算技术学习--基础概念

    目录 Linux的用户管理 Yum 命令 Python SELinux vsftpd etcd Session Cookie Token LNMP VMware Docker Kubernetes K8S Centos CentOS Com
  • ubuntu中pip3升级出现Traceback (most recent call last): File “/usr/bin/pip3”, line 9, in from pip import

    ubuntu18 04中pip3升级之后遇到这样的问题 Traceback most recent call last File usr bin pip3 line 9 in from pip import main ImportError
  • 超出表空间"users"的空间限额

    这是因为用户被数据库限制了在建表的表空间 执行一下下面的语句后 再执行建表语句 alter user 用户名 quota unlimited on 表空间名字
  • QLabel设置背景图片

    您可以使用Qt的QPalette类来设置QLabel的背景图片 以下是一个简单的示例 include
  • 2021爱分析·房企数字化厂商全景报告

    目录 1 研究范围定义 2 市场全景地图 3 市场定义与厂商评估 4 入选厂商列表 关于爱分析 研究与咨询服务 法律声明 1 研究范围定义 研究范围 本报告研究对象为房企 主要包括从事房地产开发 商写资产运营 物业服务等业务的综合性房地产企
  • [QT编程系列-20]:基本框架 - QT的测试框架QTest

    目录 第1章 QT测试框架与搭建步骤 第2章 Qt Test概述 2 1 概述 2 2 测试代码和项目代码共存 2 3 如何运行测试代码 2 4 ctest命令 第3章 单元测试代码示例 3 1 代码目录结构 3 2 代码示例 第4章 QT
  • Java写Mybatis的配置文件的注意事项

    先来聊聊properties配置文件的一些坑 1 注意自己当前使用的mysql的版本 版本低的 driver配置是 具体的版本是多少忘了 com mysql jdbc Driver 版本高的用 com mysql cj jdbc Drive
  • STM32中断与事件的区别

    STM32中断与事件的区别 在我们配置中断时 时常会困惑于什么是事件模式 EXTI InitStruct EXTI Mode 怎样选择 是选择中断模式还是事件模式 EXTI InitStruct EXTI Line EXTI Line0 E
  • IDEA 控制台输出中文乱码的简单解决方案

    目录 引言 解决方案 第一步 第二步 下载JDK 选择现有的JDK 完成 引言 很多人 包括我 在编程的时候可能会发现 在IDEA的控制台输出中文字符的时候 会出现乱码 如下图 于是就在网上搜了很多教程 结果弄完了却还是不行 下面是我的解决
  • 编译原理(第3版)第二章部分习题答案

    1 文法G A B C a b c P S 其中P为 S gt Ac aB A gt ab B bc 写出L G S 的全部元素 解 L G S 的全部元素为 a b c 2 文法G N 为 N gt D ND D gt 0 1 2 3 4
  • 修改intelliJ IDEA默认Mvnen插件镜像地址 ,加速依赖安装

    前言 1 3叙述的是如何找到idea的mvnen 如果是手动安装的Mvnen 直接跳到4 本文基于Linux平台 mac windows可作参考 如果是ToolBox安装的IDEA 那么桌面启动程序文件一般在 home USER local
  • 华为OD机试 Python 【五子棋迷】

    题目 张兵和王武喜欢玩五子棋 现在轮到张兵了 他面前的棋盘上有一排棋子 棋子规则 1 表示白子 0 表示没子 是个空位 1 表示黑子 一排棋子中 棋子数量L要满足 1 lt L lt 40 并且L是奇数 你要写个程序帮张兵找到最佳的落子位置
  • 【Apache Spark 】第 3 章Apache Spark 的结构化 API

    大家好 我是Sonhhxg 柒 希望你看完之后 能对你有所帮助 不足请指正 共同学习交流 个人主页 Sonhhxg 柒的博客 CSDN博客 欢迎各位 点赞 收藏 留言 系列专栏 机器学习 ML 自然语言处理 NLP 深度学习 DL fore
  • Tomcat提高并发量,性能优化

    系统采用的常用框架 Mysql SSM Tomcat结构 测试工具使用的是Jmeter 刚开始测试 并发量为200 s 居然错误率达到了15 让我很郁闷 按Tomcat的性能200的并发量应该完全没问题 于是我搜了一下提高Tomcat并发量
  • 区块链入门系列之P2P

    区块链入门系列文章 区块链基本概念和名词解释 P2P 共识算法 梅克尔 帕特里夏树 从零开始搭建区块链 这里写自定义目录标题 区块链入门系列文章 前言 中心化架构 去中心化架构 NAT 锥型NAT 完全锥型NAT 非完全锥型NAT IP受限
  • Devops 基础介绍

    文章目录 前言 一 软件开发概述 1 软件开发生命周期 2 软件开发瀑布模型 3 软件的敏捷开发 3 1 迭代开发 3 2 增量开发 3 3 敏捷开发如何迭代 3 4 敏捷开发的好处 二 持续集成概述 1 什么是持续集成 2 持续集成的流程
  • 嵌入式C中__attribute__编译属性说明

    锲而不舍 金石可镂 文章目录 前言 参数介绍 1 aligned 2 packed 3 at 4 section 总结 前言 attribute 是GNU C扩展下一大特性机制 用于设置函数属性 Function Attribute 变量属