关于C结构体内存对齐做的一个小实验

两条规则

关于结构体内存对齐一般考虑两条规则,首先定义一些变量,

  • 比如下面的_person结构体,其中的内部成员中,占据最大空间的设为var_max,它所拥有的字节空间为sizeof(var_max)。
  • 那么整体的大小,即这个结构体总体字节数应该是sizeof(var_max)的整数倍。

  • 结构体中一个成员变量b分配空间时,需要它的前一个成员变量a给出的下一个可用地址(也即b开始的地址,a结束的地址)是sizeof(b)的倍数,
  • 比如说分配lastname的时候,firstname给出的下一个地址是(char *)&p + sizeof(char),它是sizeof(char)的整数倍,所以不需要补足,lastname以(char *)&p + sizeof(char)作为起始地址分配自己的空间。
  • 而title分配自己空间时,lastname给它的地址是(char *)&p + 2*sizeof(char),它是sizeof(char *)的整数倍么?No,所以要地址补足,因此lastname给title的地址就变成了(char *)&p + 4*sizeof(char),lastname也就占据了3个字节的空间。

  • 如果一个结构体a中有另一个结构体变量b,那么b的最大空间难道就按照sizeof(b)来算吗?经过实验发现不是的,其实最大空间原则只考虑所有C/C++的内部定义变量,也即char, char *, int这些变量的最大大小。同理,内存对齐的补足也是依照此原则。

一个例子

_person结构体定义如下,它的内部还有个spring结构体。

typedef struct _person{
char  firstname;

char  lastname;

char * title;

unsigned int age;

char sex;

struct spring ls;
}Person;
int main()
{
	cout << sizeof(spring)  <<  endl;
	_person p;
	int size[6];
	size[0] = (char *)&p.lastname - (char *)&p.firstname;
        size[1] = (char *)&p.title - (char *)&p.lastname ;
	size[2] = (char *)&p.age - (char *)&p.title ;
	size[3] = (char *)&p.sex - (char *)&p.age ;
	size[4] = (char *)&p.ls - (char *)&p.sex ;
	size[5] = sizeof(p) - ((char *)&p.ls - (char *)&p);
	int sum = 0;
	for (int i = 0 ; i < 6; i++)
	{
		sum += size[i];
		cout << size[i] << endl;
	}
	cout << sizeof(p) << ":" << sum << endl;
}

上面的size[i]分别记录了_person中每一个成员变量占据的空间大小。

实际上_person占据的总字节大小与spring的大小是有关系的。

只有一个char的spring

首先我们定义一个简单的spring,它内部只有一个char,此时情况如何呢?

typedef struct spring{
	char a;
};


分析结果:

firstname 一个字节

---------此时就是1个字节,满足sizeof(char)对齐标准-----------

lastname 一个字节+2个补足字节

---------此时就是4个字节,满足sizeof(char *)对齐标准-----------

title 四个字节

---------此时就是8个字节,满足sizeof(unsigned int)对齐标准-----------

age 四个字节

---------此时就是12个字节,满足sizeof(char)对齐标准-----------

sex 一个字节

---------此时就是13个字节,满足sprint中最大内置变量sizeof(char)对齐标准-----------

ls 一个字节+2个补足字节

---------此时就是16个字节,满足Person中最大内置变量sizeof(char*)对齐标准-----------

spring中有5个char

下面让spring中有5个char,此时会如何呢?


firstname,lastname,title,age是不受spring的影响的,所以没有任何变化。

因为spring中内置最大变量仍旧是char,所以sex也没变化。

所以

---------此时就是13个字节,满足sprint中最大内置变量sizeof(char)对齐标准-----------

ls  5个字节+2个补足字节

---------此时就是20个字节,满足Person中最大内置变量sizeof(char*)对齐标准-----------

spring中有1个char,1个int

typedef struct spring{
	char a;
	int b;
};


spring的大小此时变为了8啦。

我们依然分析ls和sex两个。

---------此时就是12个字节,满足sizeof(char)对齐标准-----------

sex 一个字节+3个补足字节

---------此时就是16个字节,满足sprint中最大内置变量sizeof(int)对齐标准-----------

ls 8个字节

---------此时就是24个字节,满足Person中最大内置变量sizeof(char*)对齐标准-----------

spring中有1个char,1个int64

typedef struct spring{
	char a;
	uint64 b;
};


---------此时就是12个字节,满足sizeof(char)对齐标准-----------

sex 一个字节+3个补足字节

---------此时就是16个字节,满足sprint中最大内置变量sizeof(int64)对齐标准-----------

ls 16个字节

---------此时就是32个字节,满足Person中最大内置变量sizeof(int64)对齐标准-----------

下面我修改一下Person结构,把char *title改成char title,那么情况又会如何呢?

typedef struct _person{
char  firstname;

char  lastname;

char  title;

unsigned int age;

char sex;

struct spring ls;
}Person;

firstname 一个字节

---------此时就是1个字节,满足sizeof(char)对齐标准-----------

lastname 一个字节+1个补足字节

---------此时就是2个字节,满足sizeof(char )对齐标准-----------

title 1个字节+1个补足字节

---------此时就是4个字节,满足sizeof(unsigned int)对齐标准-----------

age 四个字节

---------此时就是8个字节,满足sizeof(char)对齐标准-----------

sex 一个字节+7个补足字节

---------此时就是16个字节,满足sprint中最大内置变量sizeof(int64)对齐标准-----------

ls 16个子集

---------此时就是32个字节,满足Person中最大内置变量sizeof(int64)对齐标准-----------

如此一来sex的补足字节就多了很多哦





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值