struct所占的内存

本文详细探讨了C++中结构体内存对齐的规则,包括默认对齐方式、#pragma pack(n)的影响以及含有数组、枚举、联合体等复杂结构时的内存计算。通过实例代码解析了结构体成员的排列和内存占用,并指出内存分配中需要注意的跨越对齐字节问题。
摘要由CSDN通过智能技术生成

空结构体所占内存为1 用来区分结构体

#pragma pack(n)指定按照n对齐

vs默认用8对齐

计算方式:(表面理解)

1.先找出最大的类型变量

2.在它之前的总内存必须和最大类型对齐(整数倍)

3.在它之后的总内存必须和最大类型对齐(整数倍)

深度理解:

1.每个成员按其类型大小和指定对齐参数n中较小的一个进行对齐

2.确定的对齐参数必须能够整除起始地址(或偏移量)

3.偏移地址和成员占用大小均需对齐

4.结构体成员的对齐参数为其所有成员使用的对齐参数的最大值

5.结构体总长度必须为所有对齐参数的整数倍

代码实现:

struct person
{
	int a;
	char c;
	double d;
	char e;	
};
int main()
{
	struct person p;
	cout << "p所占的内存:" <<sizeof(p) << endl;
}

struct person
{
	int a;
	int b;
	double d;
};
int main()
{
	struct person p;
	cout << "p所占的内存:" <<sizeof(p) << endl;
}

 

 当含有数组时:把数组拆分计算

struct person
{
	int b[5];
	double d;
};
int main()
{
	struct person p;
	cout << "p所占的内存:" <<sizeof(p) << endl;
}

#pragma pack(n)的使用n(1,2,4,8,16)

(当n大于最大数据类型字节时失效,取两者的小值)

  1. 先找到最大类型位置
  2. 前半部分内存和为n的倍数
  3. 后半部分也要为n的倍数

未设置#pragma pack(n)   结果为:24

struct person
{
	char c;
	double b;
	int a;
	
};

设置#pragma pack(16)   结果为:24     当n>最大数据类型时   取数据类型的值

#pragma pack(16)
struct person
{
	char c;
	double b;
	int a;
	
};

设置#pragma pack(4)   结果为:16     当n<最大数据类型时   取n

#pragma pack(4)
struct person
{
	char c;
	double b;
	int a;
	
};

设置#pragma pack(2)   结果为:14     

#pragma pack(2)
struct person
{
	char c;
	double b;
	int a;
	
};

设置#pragma pack(1)   结果为:13     

#pragma pack(1)
struct person
{
	char c;
	double b;
	int a;
	
};

复杂的结构体内存计算:

32位下:

    struct person
	{
		enum per
		{
			A,B,C,D,E
		}G;  //枚举要定义
		int a[10];
		char c;
		double b;
		int *p;
		union H
		{
			int n;
			double l;
		}Y; //结构体也要定义

	};
	person *p;
	cout << sizeof(p) << endl;//指针占4个字节(32位)    64位的话是 8个字节
	cout << sizeof(*p) << endl; //结果位 72个字节
	cout << sizeof(p->a) << endl;// 占40个字节
	cout << sizeof(p->b) << endl;// 占8个字节
	cout << sizeof(p->c) << endl;// 占1个字节
	cout << sizeof(p->d) << endl;// 指针占4个字节(32位) 
	cout << sizeof(p->G) << endl;// 占4个字节(枚举类型)
	cout << sizeof(p->Y) << endl;// 占8个字节(联合体取最大内存)

计算图解:

 注意事项:未定义的 枚举类型和联合体不占用内存

	struct person
	{
		enum per
		{
			A, B, C, D, E
		};
		
		union H
		{
			int n;
			double l;
		};
	};
	person p;
	cout << sizeof(p) << endl;//指针占1个字节空结构体占用一个字节,来区分结构体

在这里补充一个问题:(感谢评论区提出的问题)

注意内存分配的问题:

struct MyStruct
{
	int b;
	char c;
	short d;
	short e;
	char f;
	short g;
}a1;
void main()
{
	cout << sizeof(a1) << endl;
}

 

如果按照正常的计算方法:

int 为最大类型  对齐字节为 4

所以 cdefg相加的结果为 1+2+2+1+2=8 刚好为4的倍数,所以结果为12  但结果为16

这里需要注意一个细节,就是跨越对齐字节问题,

(当一个数据跨越了两个对齐字节时,当存放不下时需要额外的分配一个对齐字节,不得跨越对齐字节)

struct MyStruct
{
	int b;
	char c;
	short d;
	short e;
}a1;
void  main()
{
    printf("%p\n", &a1.b);//获取地址
	printf("%p\n", &a1.c);
	printf("%p\n", &a1.d);
	printf("%p\n", &a1.e);
	cout << sizeof(a1) << endl;
}

 

这里结果为12 ,它的内存分配解释如下:

一般会以为:c+d+e=5,然后在5后面补充3个字节

实际上:由于c+d=3   4-3=1  1个字节存放不了 e(2个字节),所以补充一个字节,

然后开辟新的4个字节    存放 e+2(两个补充字节)

 图解为:

 返回到之前的问题:结果为什么为16

计算方式为:(红字为填充)

4 + (1+2+1) +(2+1+1)+(2+2)=16

 图解为:

再例如:

struct MyStruct
{
	char a;
	int b;
	int c;
	double d;
}a1;
void  main()
{
	printf("%p\n", &a1.a);
	printf("%p\n", &a1.b);
	printf("%p\n", &a1.c);
	printf("%p\n", &a1.d);
	cout << sizeof(a1) << endl;

}

 

 还有补充有多个最大数据类型时的计算:

计算方法为:把最大类型变量当作节点,节点左右两边的类型字节对齐。

struct MQ
{
	char a;
	int b;
	char c;
	short d;
	short e;
	char f;
	short g;
	int h;
	char k;
};
void  main()
{
	cout << sizeof(MQ) << endl;

}

计算过程为:

 

评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值