两种字节对齐指令

在操作结构体的时候,通常面临字节不能对其的情况,这时候使用字节对其指令可以完美的解决这个问题

两种对齐指令的介绍

#pragma pack(n) 和 attribute((aligned(n))) 是两种用于调整结构体内存对齐方式的手段,它们的主要作用是确保结构体中的成员按特定的字节边界进行排列,以减少或消除编译器默认插入的填充字节。
1、#pragma pack(n) 方式
#pragma pack 是一种预处理指令,用于调整结构体、联合体以及类成员的对齐方式。它可以通过指定字节数来强制所有成员按特定的字节边界对齐。#pragma pack(4) 会将结构体的所有成员强制对齐到4字节边界。即使成员的自然对齐大小小于4字节(如 uint8_t 或 uint16_t),它们也会根据4字节对齐规则进行存储。

优点:
全局作用:可以影响多个结构体定义,适合在较大范围内统一调整对齐规则。
兼容性好:很多编译器支持 #pragma pack,因此它在跨平台代码中使用较为广泛。
通过 #pragma pack(n) 可以确保结构体的内存占用更为紧凑,并且按指定的对齐规则进行存储,适用于硬件需要特定对齐规则(如Flash写入)的场景。

缺点:
不同编译器对 #pragma pack 的支持可能有所差异。
过度使用 #pragma pack 可能会影响性能,因为某些处理器更适合在其自然对齐边界上访问数据。
细粒度控制较弱:#pragma pack(n) 会影响所有后续的结构体,如果你希望仅对某个结构体进行调整,需要手动恢复默认对齐 (#pragma pack()),操作较为繁琐。
仅改变内部成员的对齐:它只改变结构体内部成员的对齐方式,而不能调整整个结构体的对齐边界

2、attribute((aligned(n))) 方式
attribute((aligned)) 是 GCC 和一些其他编译器(如 Clang)提供的编译器特性,用于设置变量、结构体或类型的对齐方式。 attribute((aligned(4))) 会将结构体或变量的每个成员对齐到至少4字节边界。如果某个成员的自然对齐方式需要比 4 更大的对齐(比如 uint64_t 需要8字节对齐),则该成员仍然按其自然对齐方式对齐

优点:
通过 #pragma pack(4) 可以确保结构体的内存占用更为紧凑,并且按指定的对齐规则进行存储,适用于硬件需要特定对齐规则(如Flash写入)的场景。
更灵活:可以单独控制某个变量或结构体的对齐,而不需要改变其他代码的对齐方式。
精细化控制:不仅可以控制结构体成员的对齐,还可以控制整个结构体的对齐。
缺点:
不同编译器对 #pragma pack 的支持可能有所差异。
过度使用 #pragma pack 可能会影响性能,因为某些处理器更适合在其自然对齐边界上访问数据
编译器支持依赖:虽然很多现代编译器都支持 attribute,但在某些平台上可能不如 #pragma pack 的支持广泛。
语法复杂性:在定义每个变量或结构体时都需要单独添加 attribute((aligned(n))),如果有很多结构体需要调整,代码可读性可能稍差
3、具体使用案例(对于Flash)

#pragma pack(4)  // 强制4字节对齐
typedef struct {
    uint8_t data1;       // 1字节
    uint16_t data3;  	 // 2字节
    uint32_t data4;   	 // 4字节
    uint32_t data5;  	 // 4字节
} DATA_NAME;
#pragma pack()   // 恢复默认对齐
typedef struct {
    uint8_t data1;    // 1字节
    uint16_t data3;   // 2字节
    uint32_t data4;   // 4字节
    uint32_t data5;   // 4字节
} __attribute__((aligned(4))) DATA_NAME;

使用#pragma pack(4)或者__attribute__((aligned(4)))后,编译器会强制将结构体成员对齐到4字节的边界。这样,在写入和读取时,结构体的内存布局将保持一致,且满足Flash对齐的要求。
在这里插入图片描述
**#pragma pack(4) 或 attribute((aligned(4))):**结构体的成员强制对齐到 4 字节边界,总大小为 16 字节。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值