0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

结构体对齐在STM32中的具体体现和如何进行不同对齐方式的设置

玩转单片机与嵌入式 来源:玩转单片机与嵌入式 2023-08-22 09:31 次阅读

引言

嵌入式系统开发中,结构体作为一种常见的数据组织方式,在内存中的布局方式对于程序性能和内存占用具有重要影响。本文将深入探讨单片机C语言中的结构体对齐原理、重要性以及不同的对齐方式,并通过示例演示结构体对齐如何影响内存占用、访问性能以及传输与存储。同时,我们将关注STM32这样的嵌入式系统,讨论结构体对齐在STM32中的具体体现和如何进行不同对齐方式的设置。

结构体对齐原理

1、为什么需要对齐?

在计算机内存中,数据的存储通常需要按照一定规则进行,这被称为内存对齐。内存对齐的目的是为了提高访问数据的效率,特别是对于硬件平台而言。不同的处理器架构可能有不同的对齐要求。

2、不同的对齐方式

单字节对齐(Byte Alignment):每个数据类型从内存的任意地址开始存储,不需要对齐到特定字节边界。

双字节对齐(Half-Word Alignment):数据类型的变量必须从内存的偶数地址开始存储,即地址必须是2的倍数。

四字节对齐(Word Alignment):数据类型的变量必须从内存的4字节边界开始存储,即地址必须是4的倍数。

3、结构体对齐示例

下面的C代码示例演示了不同对齐方式在内存中如何存储一个简单的结构体。

#include 


// 结构体定义
struct Example {
    char a;
    int b;
    char c;
};


int main() {
    struct Example e;


    // 计算各成员的地址
    printf("Address of a: %p
", &e.a);
    printf("Address of b: %p
", &e.b);
    printf("Address of c: %p
", &e.c);


    return 0;
}

在这个示例中,我们定义了一个名为Example的结构体,包含一个字符a、一个整数b和一个字符c。通过printf语句,我们可以查看不同对齐方式下各成员的地址。该结构体在内存中存储的方式如下:

9526646a-4077-11ee-ac96-dac502259ad0.png

喜欢的读者可以自行打印确定printf的输出结果,观察不同的地址有何规律。

4、结构体对齐的影响

(1)内存占用

结构体对齐可以影响内存的占用情况。考虑以下示例:

struct Example1 {
    char a;
    int b;
    char c;
};


struct Example2 {
    char a;
    char b;
    char c;
};

在示例1中,int类型需要四字节对齐,因此struct Example1的大小为12字节。而在示例2中,所有成员都是字符类型,无需对齐,因此struct Example2的大小为3字节。这突显了对齐规则如何影响内存占用。

(2)访问性能

结构体对齐还会影响访问性能。在访问一个结构体变量的成员时,如果成员没有正确对齐,可能需要多次内存访问操作,从而降低了访问速度。合适的对齐可以减少内存访问次数,提高程序性能。

(3)传输和存储

结构体对齐也会影响数据的传输和存储。当结构体作为数据包进行传输时,如果接收端和发送端的对齐方式不一致,可能需要进行字节序转换,以确保数据的正确传输。

这增加了编程的复杂性,因为程序员需要处理不同对齐方式可能导致的字节序问题。

下面是一个传输和存储的C代码示例,演示了在不同对齐方式下数据的传输和存储:

#include 
#include 


// 结构体定义
struct SensorData {
    uint16_t sensor1;
    uint32_t sensor2;
} __attribute__((packed));  // 使用编译器指令取消结构体对齐


int main() {
    struct SensorData data;
    data.sensor1 = 0x1234;
    data.sensor2 = 0x56789ABC;


    // 数据存储到内存中
    uint8_t buffer[sizeof(struct SensorData)];
    memcpy(buffer, &data, sizeof(struct SensorData));


    // 模拟传输过程
    // 接收端假设数据是按照双字节对齐方式接收
    struct SensorData* receivedData = (struct SensorData*)buffer;


    printf("Received sensor1: 0x%04X
", receivedData->sensor1);
    printf("Received sensor2: 0x%08X
", receivedData->sensor2);


    return 0;
}

在这个示例中,我们定义了一个SensorData结构体,包含一个16位整数和一个32位整数。使用__attribute__((packed))编译器指令取消了结构体对齐,以确保数据在内存中是连续存储的。然后,我们将数据存储到内存中,并模拟了传输过程。接收端假设数据是按照双字节对齐方式接收,但由于我们取消了对齐,需要进行字节序转换。

结构体对齐在STM32中的体现

1、外设寄存器对齐要求

在STM32这样的嵌入式系统中,外设寄存器通常要求双字节或四字节对齐,以确保寄存器的访问性能和正确性。不满足对齐要求可能导致未定义的行为或性能问题。

在STM32中,可以使用编译器指令来实现对齐设置。例如,在Keil工程中,可以使用__align()指令来指定对齐方式。例如,要将一个结构体成员对齐到4字节边界,可以这样定义:

struct Example {
    char a;
    int b;
    char c;
} __attribute__((aligned(4)));

2、内存池分配

在嵌入式系统中,经常使用内存池来分配内存。内存池分配会确保分配的内存块是按照对齐要求进行的,以满足处理器的要求。这可以防止未对齐内存访问,提高代码的稳定性和可靠性。

在STM32中,常用的内存池分配库如FreeRTOS提供了对齐设置的选项,以确保分配的内存块满足处理器的要求。

3、DMA操作

嵌入式系统中常常使用DMA(直接内存访问)来进行数据传输。DMA操作通常要求数据缓冲区是双字节或四字节对齐的。不满足对齐要求可能导致DMA传输失败或性能下降。

在STM32中,配置DMA时可以使用寄存器来设置数据对齐方式,以确保DMA传输的正确性和性能。

结论

作为嵌入式工程师的我们。在编写代码时,程序员需要根据目标硬件平台的对齐要求。






审核编辑:刘清

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 处理器
    +关注

    关注

    68

    文章

    19312

    浏览量

    230030
  • 单片机
    +关注

    关注

    6037

    文章

    44563

    浏览量

    635863
  • 存储器
    +关注

    关注

    38

    文章

    7494

    浏览量

    163912
  • STM32
    +关注

    关注

    2270

    文章

    10904

    浏览量

    356335
  • C语言
    +关注

    关注

    180

    文章

    7605

    浏览量

    136993

原文标题:结构体对齐原理及在STM32中的设计原则和实现

文章出处:【微信号:玩转单片机与嵌入式,微信公众号:玩转单片机与嵌入式】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    C语言结构对齐介绍

    大家好,我是嵌入式老林,从事嵌入式软件开发多年,今天分享的内容是C语言结构对齐介绍,希望能对你有所帮助
    发表于 07-11 11:50 2534次阅读
    C语言<b class='flag-5'>结构</b><b class='flag-5'>体</b><b class='flag-5'>对齐</b>介绍

    C语言-结构对齐详解

    4字节对齐处存放,结构对齐后的大小必须4的倍数,如果编译器设置为8字节对齐,则这里的4就是8。
    发表于 07-12 16:41

    CCS3.3 结构成员对齐

    : expected a type specifier error: expected a ";" 这个错误。是CCS3.3编译器本身不支持__packed这种结构成员的对齐方式
    发表于 06-21 10:16

    请问ccs4.2 怎么设置结构的字节对齐

    请问ccs4.2 怎么设置结构的字节对齐,用于网络数据发送的。是:]__attribute
    发表于 08-02 07:47

    请问z-stack结构默认对齐方式是一字节吗?

    z-stack的结构默认对齐方式是一字节吗?z-stack可以将一般指针强制转换为
    发表于 08-18 07:38

    测试结构成员内存对齐方式方法

    //测试环境:keil for ARM//测试目的:通过keil仿真,介绍结构成员对齐方式 #pragma pack ()//定义一个联合体类型 struct stru {int a
    发表于 12-21 07:37

    ARM内存边界对齐以及sizeof问题

    默认情况下,32位cpu里,gcc对于结构对齐方式是按照四个字节来对齐的。
    发表于 06-16 11:10 2962次阅读

    CSS对齐方式的详细讲解

    本文基于Html基础,主要介绍了Html对齐方式,对于对齐的标签做了详细的讲解,用丰富的案例 ,代码效果图的展示,帮助大家更好理解 。
    的头像 发表于 12-24 15:38 1287次阅读

    解析C语言结构字节如何对齐

    我们不使用宏#pragma pack,采用默认字节对齐方式。 先抛出结论: 一个结构第一个
    的头像 发表于 06-12 17:42 3086次阅读

    STM32 终极字节对齐解析

    字节对齐。uint64_t定义变量地址要8字节对齐。指针变量是4字节对齐。二、结构成员对齐问题
    发表于 11-23 18:06 11次下载
    <b class='flag-5'>STM32</b> 终极字节<b class='flag-5'>对齐</b>解析

    结构对齐理解上有点偏差

    总结一下: 结构对齐不再是简单的字节个数的拼凑,而是要与内存地址进行挂钩~一般我们也可以理解为内存地址分配是多少字节的倍数,就是多少直接对齐
    的头像 发表于 08-10 18:08 1206次阅读
    对<b class='flag-5'>结构</b><b class='flag-5'>体</b>的<b class='flag-5'>对齐</b>理解上有点偏差

    结构对齐为什么那么重要?

    以前我也没觉得懂得这个结构对齐或者内存对齐有多重要,直到已经从事了嵌入式开发经验不断积累,才慢慢体会到,这是一种很基础的知识,就因为这个东西不常用,而出现相关的问题是非常致命的,排查
    的头像 发表于 04-03 10:13 1403次阅读

    为什么要结构对齐?为什么结构对齐那么重要?

    C语言结构对齐问题,是面试必备问题。我参与招聘技术面试的时候,也喜欢问这个技术点。
    的头像 发表于 05-26 14:10 1286次阅读
    为什么要<b class='flag-5'>结构</b><b class='flag-5'>体</b><b class='flag-5'>对齐</b>?为什么<b class='flag-5'>结构</b><b class='flag-5'>体</b><b class='flag-5'>对齐</b>那么重要?

    keil arm工程结构1字节对齐如何实现

    的默认对齐方式和规则 结构Keil Arm工程的默认
    的头像 发表于 01-05 14:40 3844次阅读

    鸿蒙ArkUI开发:【弹性布局(主轴&amp;交叉轴对齐方式)】

    通过justifyContent参数设置主轴方向的对齐方式,和Row、Column的主轴对齐方式
    的头像 发表于 05-14 15:33 749次阅读
    鸿蒙ArkUI开发:【弹性布局(主轴&amp;交叉轴<b class='flag-5'>对齐</b><b class='flag-5'>方式</b>)】