字节对齐学习笔记

本文详细探讨了嵌入式系统中字节对齐的概念,包括总体规则、结构体嵌套、对齐方式及如何通过#pragma pack进行强制转换。通过实例解析了结构体中位域分配的问题,强调了位域分配受变量类型影响并可能导致内存对齐问题。文章旨在帮助读者更好地理解和处理嵌入式编程中的内存管理问题。
摘要由CSDN通过智能技术生成

字节对齐学习笔记

在观看嵌入式学习视频时有一道关于地址对齐的题目,发现自己有很多不清楚的地方,而且这一部分有很多案例需要分情况讨论,所以单独写一篇文章来总结一下。

1.总体规则
在进行结构体的地址对齐时,总是以结构体中最大的数据类型为标准进行对齐,数组只看其数据类型,不看具体大小。
注意:指针的大小要看操作系统是32位还是64位。
举个栗子:引自结构体嵌套对齐

struct S1 {
	char a;// 0
	double b;// 8-15
	short c[2];//16-19,因为double的8比short的2大,引用规则一
	//共24
};

结构体S1中,最大的数据类型为double,所以整体要以8byte进行对齐。

2.结构体嵌套
结构体S2中嵌套结构体(或联合体)S1,则按照S1的最大元素类型和S2中各元素类型取较大者对齐

struct S2 {
	struct S1 a;// , 0-23
	int b;//24-27
	char c;//28
	// 最后按S1的最大类型double的8字节对齐,因为double比S2的int和char字节数都大,最后
	//整个S2按照8字节对齐
};

结构体S2中,由于嵌套了结构体S1,而两者中最大的数据类型仍是S1中的double,所以S2也是以8byte进行对齐。

3.如何对齐
S2中的b数据类型为int,是4byte,占据24-27,c的数据类型为char,是1byte,加上b的4byte小于8byte,所以c的地址直接接在b的后面,而不是从32开始。
如果c的数据类型大于4byte,即接在b后面会无法对齐,此时c的地址会从32开始。

4.强制转换
可以使用#pragma pack()进行数据对齐的强制转换,#pragma pack(4)即转化成4位对齐

5.嵌套 + 位域——内存对齐
下面这个栗子引用自:有关联合体嵌套结构体 、位域(位段)、小端存放
在结构体划分位段时,会受到自身变量类型的影响。如果该类型剩余空间不足以继续分配位段,则会自动对齐至下一个内存单元中,进行分配。
错误代码:

union MyUnion
{
	unsigned short num;	// 16 位
	struct 
	{
		unsigned char al : 6;	// 低 6位
		unsigned char ah : 6;	// 中 6位
		unsigned char hh : 4;	// 高 6位
	};
};

int main()
{
	MyUnion un;
	un.num = 0x111;	// 0000 0001 0001 0001
	int n = un.hh;  //error: 使用了未初始化的局部变量“un”

	return 0;
}

al首先占据了num低字节位的前6位,在ah想要继续往下占据的时候,由于它们是char类型,只有8位,减去al的6位,此时只剩下2位,不够分配给ah,所以将会进行对齐,导致ah占据num高字节位的前8位,而不是与al地址连续。即:
unsigned char al : 6;低 6位=0000 0001 0001 0001
unsigned char ah : 6;高 6位=0000 0001 0001 0001
正确改法:
unsigned char;类型换成 unsigned short;,使之在内存对齐时,使用2字节对齐。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值