MDK中结构体的对齐、位域、配合联合体等用法说明

测试环境:STM32H7R3+MDK 5.39+AC5

注:PC、PowerPC等环境不适用本文。

一.字节对齐

        一般采用自然对齐(默认方式),提高数据存取速度。
        采用1字节对齐,变量在内存中无空隙,紧密存储,节省存储空间。另外可配合union,在通信时进行数值(void*)与tx/rx缓冲区(uint8_t*)的相互转换。


1.默认方式

#include <stdint.h>

typedef struct {
	uint8_t A;
	uint16_t B;
	uint16_t C;
}Test_T;

int main(void)
{
    Test_T Test={
                .A=0x11,
                .B=0x2222,
                .C=0x3333,
    };

    return 0;
}

内存图:

为保证自然对齐,成员在内存中有空隙。

uint16_t成员A占2字节,起始地址0x200003ED%2=1,非2字节对齐,而0x200003EE%2=0,满足对齐条件。

2.强制1字节对齐

#include <stdint.h>

#pragma pack(push, 1)
typedef struct {
	uint8_t A;
	uint16_t B;
	uint16_t C;
}Test_T;
#pragma pack(pop)

int main(void)
{
    Test_T Test={
                .A=0x11,
                .B=0x2222,
                .C=0x3333,
    };

    return 0;
}

内存图:
变量在内存中紧密排列,无空隙

二.位域

        C语言最小的数据类型是字节(8bit) ,我们只能选择8/16/32bit去存储数据。在某些应用中,数据需要更灵活的数据类型来存储,如开关量0/1只需要1bit来存储;考试成绩0~100只需要7bit来存储。

        通过位域,可在结构体实现指定bit数的存储。且成员数据类型只能为整型。

typedef struct {
	uint8_t 	A:1;
	uint16_t 	B:4;
	uint16_t 	C:7;
}Test_T;

Test_T Test={
.A=0b1,
.B=0b0000,
.C=0b1111111,
};

        此时Test_T的各成员数据类型(uint8_t、uint16_t)的作用,是限制位域成员的最大bit数,以及该位域的值应被如何解释。

         在未指定1字节对齐时(#pragma pack(push, 1)),位域结构体在内存中仍有空隙,对齐方式与成员类型以及位域大小有关。详见博文(C语言笔记)位域的详解使用(含内存对齐)所以在需要形成连续比特流的场合,需要位序配合1字节对齐使用。

                注:Test_T的各成员的大小是非字节倍数的,无法用sizeof(Test_T.A)计算空间。但由各位域成员组成的结构体变量,仍可用sizeof(Test_T)计算大小。Test_T的各成员也无法通过指针操作。


        

三.联合体

        在通信中使用,可将有意义的数值转为字节缓冲区,即可实现快速组帧。

四.三者配合使用

如下有效利用资源,实现通信协议对数据的高度压缩。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值