结构体内存对齐 & 联合体大小计算

一:结构体内存对齐规则

  • 1.第一个成员在结构体变量偏移量为0的地址处。

  • 2.从第二个成员变量开始,要对齐到对齐数的整数倍 地址处。
    对齐数 就是 编译器默认的一个对齐数 与 该成员大小中的 较小的那一个。

    • VS编译器默认的对齐数是8(字节), Linux中默认对齐数是4
  • 3.结构体总大小 是每个成员变量的对齐数 中最大的对齐数的整数倍。

  • 4 如果结构体中嵌套了另外一个结构体,那么就把这个嵌套在里面的结构体当成外面结构体的一个成员,里面的结构体的对齐到自己的最大对齐数的整数倍,(这时里面的结构体也有一个最大对齐数,把这个对齐数就当做里面的结构体的对齐数),所以整体大小就是最大对齐数的整数倍。

  • 注意:32位平台下,vs的默认对齐数是4字节,但是在64位平台下,vs的默认对齐数是8字节。

二:内存对齐的大小计算

在这里插入图片描述

如何修改默认对齐数:

修改默认对齐数: 使用 #pragma pack(n)
恢复默认对齐数: 使用 #pragma pack()

修改默认对齐数后的结构体大小:
在这里插入图片描述

//穿插一个结构体只是验证
struct S
{
	float f;  //4   ---4
	short s;   //2    ---2(4)
	int i;     //4    ----4
	double d;    //8  ----8(4+8)
	char c;   //1      ----1
	int a[4];  //16   ----16(3+16) 
			                  //4+4+4+12+1+19=44,  结构体大小应该是48,经过验证,结果正确
};


struct B
{
	float f;  //4   ---4
	short s;   //2    ---2(4)
	int i;     //4    ----4
	char c;   //1      ----1
	char a[7];  //7   ----7  ---对齐数是1,不是7,说明了数组的对齐数是对应元素的类型大小,而不是数组的大小
							  //4+4+4+1+7=20,  结构体大小应该是20,经过验证,结果正确
};


int main()
{
	int a[4];
	cout << sizeof(S) << endl;    //40
	cout << sizeof(B) << endl;    //20

	cout << sizeof(float) << endl;   //4
	cout << sizeof(short) << endl;   //2
	cout << sizeof(double) << endl;  //8
	cout << sizeof(a) << endl;      //16
	return 0;
	}

三:结构体内存对齐原因

为什么要有结构体内存对齐?
原因:
(1)方便移植,因为不是所有的硬件平台都能任意访问任意地址上的任意数据,某些硬件平台只能在某些地址处取某些特定类型的数据,否则会抛出硬件异常。
(2)有利于性能的提升,如果内存没有对齐,处理器需要做两次内存访问;而对齐的内存的访问仅需要一次。所以数据结构应该尽可能的在自然边界上对齐。
(3)内存对齐实质上是一种以空间换区取时间的做法,因此在设计结构体的时候,应该既要满足对齐,又要节省空间,可以采取让占用空间小的成员尽可能的其中在一起。



联合体(共用体)

1.定义:

联合体是一种特殊的自定义类型,联合体变量包含一系列成员,这些成员公用同一份内存空间

//联合体的声明
union Un
{
		int a;
		char b;
}

//联合体的定义
union Un un;   //un就是联合体变量

//计算联合体大小
printf("%d\n",sizeof(un));

2.联合体大小的计算规则:

满足以下两点:

  • 联合体的大小 >= 最大成员的大小
  • 当最大成员大小不是最大对齐数的整倍数时, 要对齐到最大对齐数的整数倍(对齐的结果是超过并接近最大成员大小)。
例如:求联合体Un1的大小?在这里插入图片描述
分析:

1.变量c 是个短整型数组,有七个元素,大小是14字节,vs编译器默认的对齐数是8字节,所以两者最终的对齐数(取较小的对齐数作为变量的对齐数)是8字节。
2.变量i 是个整型变量,大小是4字节,vs编译器默认的对齐数是8字节,所以最终变量i的对齐数是4字节。
3.所以,整个共用体的最大对齐数为变量c的对齐数----8。但是考虑到最大成员的大小14不是8的倍数,所以要对齐到8的整数倍----16。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值