内存对齐:位段大小


内存对齐的原因

  1. 平台原因:不是所有的的硬件平台都能访问任意地址上的任意数据;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。
  2. 性能原因:对齐的内存访问可以省时,相当于说,内存对齐是拿空间换时间的做法。

结构体的内存对齐是拿空间来换取时间的做法。

内存对齐规则

  1. 第一个成员在与结构体变量偏移量为0的地址处。
  2. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。 对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。 VS中默认的对齐数为8,Linux中的默认的对齐数为4。
  3. 结构体总大小为最大对齐数(每个成员变量除了第一个成员都有一个对齐 数)的整数倍。
  4. 如果嵌套了结构体的情况,嵌套的结构体的对齐数是自己成员变量的最大对齐数

空类的计算

空类的大小是:1个字节,用来占位。
这里写图片描述

嵌套结构体大小

struct Node1{
	int a;			
	char c;
};
struct Node2
{
	int data;		   //对齐数是0,大小是4
	struct Node1 node;//默认对齐数是Node1的成员最大对齐数4,大小是8
};
int main()
{
	cout<<sizeof(Node2) << endl;//结果是12
}

栗子说明结构体设计原则

  • 让占用空间小的成员尽量集中在一起。
struct A
{					  		 //对齐数	至此所占内存大小
	char d = 'a';			 //  0			 1
	short b = 2;			 //	 2	         4	
	int a = 20;				 //  4			 8
	long c = 8;				 //  4			12
}x;
struct B{					 //对齐数	至此所占内存大小
	int a = 20;				 //  0			 4
	short b = 2;			 //  2			 6
	long c = 8;				 //  4          12
	char d = 'a';			 //  1 		    16
}y;

我们看到,仅仅是因为结构体中成员的先后顺序不同就会造成,结构体大小不同。那在设计结构体的时候,我们既要满足对齐,又要节省空间,如何做到:让占用空间小的成员尽量集中在一起。

  • 结构体传参的时候,要传结构体的地址。

位段大小计算

  1. 位段的成员可以是 int unsigned int signed int 或者是 char (属于整形家族)类型。
  2. 位段的成员名后边有一个冒号和一个数字,数字代表改成员变量所占的位数。
  3. 位段的空间开辟:如果结构体中只含有char类型成员,则结构体以1字节为单位开辟空间,否则以4字节开辟空间。
struct A
{
	int _a : 2;			
	int _b : 5;
	int _c : 10;
	int _d : 30;
};

int类型按照4字节大小开辟空间,第一块四字节空间可以存下_a、_b、_c,因为2+5+10<=32,_d只能重新开辟4个字节,所以结果是8字节。

struct S
{
	char a : 3;
	char b : 4;
	char c : 5;
	char d : 4;
};

char类型按照1字节大小开辟空间,第一块1字节空间可以存下a、b,因为3+4<=8,_c、_d只能重新开辟2个字节,分别存储,所以结果是3字节。

struct C
{
	char a : 3;
	char b : 4;
	int c : 10;
	int d : 30;
};

答案是12,存在int,该结构体以4字节开辟空间,第一块空间可以存下a和b,还需要两块四字节空间f分别存储c和d,总共12字节。

struct C
{
	char a : 3;
	char b : 4;
	long long int c : 30;
};

答案是16。4+8存储数据,结构体总大小要是最大对齐数的整数倍,最大对齐数是8,所以结果是16。

猜你喜欢

转载自blog.csdn.net/Vickers_xiaowei/article/details/89681497
今日推荐