内存对齐(struct ,calss)、位段

一、内存对齐:

编译器将程序(class ,struct,union)中的每个数据(成员变量)安排在适当的位置上。

许多编译器对数据在内存中的存放顺序是有限制的,他们要求这些数据的首地址必须是某个数的整数倍(通常为4/8)

class的大小是其成员变量的和,其成员函数是所有对象共享的,并不占空间

二、为什么要内存对齐?

1.平台原因

不是所有硬件平台都可以访问任意地址上的任意数据,某些平台只能在某些地址处取一些特定的数据,否则会抛出硬件异常

(编址并不是对所有的内存进行编址,所以有些内存不能访问)

2.性能原因:

数据结构应该尽可能的在自然边界对齐,原因是,为了访问未对齐的内存处理器可能需要做俩次内存访问,而对齐的内存只需要访问一次,这样就会提升cpu的访问速率。

内存对齐是以空间换时间的做法

三、内存对齐规则

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

2.其他成员变量对齐在对齐数的整数倍的地址处

//对齐数 = min(编译器默认对齐数,该成员的大小)

vs默认对齐数 8    

gcc默认对齐数4    

3.结构体的总大小为最大对齐数的整数倍

4.结构体如果镶套了结构体,镶套结构体对齐到自己的最大对齐数的整数倍,结构体的总大小是所有最大对齐数的整数倍。

class Class1
{
	char c1;   //对齐到偏移量为0的地址处 (下一个位置偏移量为1)
	int i;     //min(4,8(vs))= 4,对齐到偏移量为4的地址处(下一个位置偏移量为8),
	char c2;   //min(1,8) = 1,对齐到偏移量为8的地址处(下一个位置偏移量为9)
	double d;   //min(8,8) =8,对齐到偏移量为16的地址处
};

int main()
{
	Class1 c;
	cout << sizeof(c) << endl;
 	system("pause");
	return 0;
}

class Class1
{
	char c1;
	int i;
	char c2;
	double d;
};
class Class2
{
	char a;   //0(占1字节) —— 1
	class Class1 b;//8(占24字节)——32
	int c; //32(占4字节)——36
	//最大对齐数为8,36不是8的整数倍,取四十
};

int main()
{
	Class2 c2;
	cout << sizeof(c2) << endl;
 	system("pause");
	return 0;
}


注:在设计结构体的时候,尽量让占空间小的成员集中在一起,这样可以节省空间


三、位段

1. 什么是位段

位段的声明和结构体很相似,但是有俩个不同

1)位段的成员必须是int、unsigned int 、signed int、char(属于整型家族)

2)位段的成员后面有一个冒号和一个数字(表示bit)

2.位段分配内存的方式

1)位段的空间是按照4(int)个字节或1(char)个字节来开的

2)位段涉及很多不确定因素,位段是不跨平台的,注重可移植性的程序应避免使用

eg1:

struct A
{
	int _a : 2;
	int _b : 5;
	int _c : 10;
	int _d : 30;
};

int main()
{
	cout << sizeof(struct A) << endl;// 8个字节
 	system("pause");
	return 0;
}

eg2:

eg3:


1.当给位段赋值超过它所能表示的范围就会被丢弃(a._a-> _a:3 ; 10->1010  ;输出2(010))

2.int位段被当成有符号还是无符号数是不确定的(a._b ->_b:4 ; 12->1100;  输出-4)

3.位段中的成员在内存是从左向右分配的,还是从右到左不确定

4.当一个结构体包含俩个位段,第二个位段成员比较大,无法容纳于第一个,第一个成员剩余的位是利用还是丢弃,不确定


跟结构体相比,位段可以达到相同的效果,还可以更好的节省空间,就是存在跨平台的问题




猜你喜欢

转载自blog.csdn.net/audience_fzn/article/details/80400115