结构体大小

举报
IM_STONE 发表于 2022/07/25 22:09:45 2022/07/25
【摘要】 1、结构体大小由成员变量和偏移量相加而成; 2、其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处,整体大小也要能被对齐数整除 总对齐数: = 编译器默认的一个对齐数与该成员大小的较小值, 也就是m...

1、结构体大小由成员变量和偏移量相加而成;
2、其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处,整体大小也要能被对齐数整除

总对齐数: = 编译器默认的一个对齐数与该成员大小的较小值, 也就是min{编译器默认的对齐数成员变量大小的最大值},VS中默认的对齐数为8;

单个对齐数:该类型变量所占内存大小,char 对齐数是1 ,int 对齐数是4 , double 是8 , 32位指针类型是4 , 64位指针类型是8;

对齐原则分两步:

1、单个成员变量对齐(也就是说,单个变量的起始地址能被单个对齐数整除)
2、整体对齐(整体大小能被对齐数整除,若不能不整除,则增加偏移来填充)

相同的成员变量,因为声明位置不同,导致占用内存空间不同,看下面代码


void test6()
{
//总对齐数min{编译器默认的对齐数=8 ,成员变量大小的最大值double=8 } = 8
	struct node
	{
		//假设总体空间为all 
		double m;//8   double对齐数为8  ,此时all=8  [0:7]
		int a;//4           int 对齐数为 4        all=12 [8:11]
		char c;//1        char对齐数  1         all=13   [12]
		char b;//1        char对齐数  1        all=14    [13]
	};//16               **开始整体对齐,要能被整体对齐数整除,也就是能被8整除,14不能被8整除,+2=16 即可,所以all=16**

	struct node1
	{
		char c;		//1	 char对齐数  1         all=1
		int a;//4	       int对齐数  4  (char c 后空出三个字节,从第四个字节开始存放 int a)       all=8
		char b;			//1  char对齐数  1         all=9
		double m;//8    double对齐数为8  (char b 后空出7个字节,从第四个字节开始存放double m) ,此时all=24
	};//24     24能被8整除,所以整体不需要偏移

	cout << sizeof(node) << "---" << sizeof(node1) << endl;
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

单个成员变量对齐(也就是说,单个变量的起始地址能被单个对齐数整除)更加通俗的讲就是;double类型必须从被8整除的地址开始,int 必须从被4整除的地址开始,若起始地址不能被整除,则向后移动,直到能被整除,空出来的空间直接浪费,用空间换时间。

如果嵌套了结构体的情况,内层嵌套的结构体成员对齐到自己的最大对齐数的整数倍的地址,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。

为什么要偏移
平台的原因(移植原因):不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取到某些特定类型的数据,否则抛出硬件异常。
性能的原因: 数据结构(尤其是栈)应该尽可能的在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。

文章来源: blog.csdn.net,作者:IM-STONE,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/doubleintfloat/article/details/125957416

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。