结构体和联合体的一些问题

结构体在内存中的对齐规则

  1. 结构体变量的首地址,必须是结构体变量中最大基本数据类型成员所占字节数的整数倍。
  2. 结构体变量中的每个成员相对于结构体首地址的偏移量,都是该成员基本数据类型所占字节数的整数倍。
  3. 结构体变量的总大小,为结构体变量中最大基本数据类型成员所占字节数的整数倍。

不好理解,用例子来看

示例

示例1

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

int main(void)
{
	struct node S1;

	printf("size of S1 is %d\n", sizeof(S1));

	return 0;
}

结果:
在这里插入图片描述

原因:
结构体中的成员是按照定义顺序一个一个放入内存的,但并不是紧密排列。
从结构体存储的首地址开始,每个元素放置到内存中时,都会认为内存是以它自己的大小来划分的,因此元素放置的位置一定会在自己的所占字节数的整数倍上开始。

就上个例子来说,当系统为a开辟空间后,再存放整型变量b时,会以四个字节为单位进行存储,但第一个四字节块已经被a占了,所以b会存到下一个四字节块中,同理double类型的变量c会以八字节进行存储,第一个八字节块有数据,就找下一八字节块。
在这里插入图片描述在这里插入图片描述

示例二

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

该变一下b和c的类型,我这里相当于把double类型放到第二个位置
运行结果:
在这里插入图片描述

这说明了规则的第三条:
结构体变量的总大小,为结构体变量中最大基本数据类型成员所占字节数的整数倍。

当为最后一个int类型变量开辟空间后,发现总大小不是最大类型double所占字节数的整数倍,那就要补齐。
图示:
在这里插入图片描述

为什么要理解字节对齐问题

总结:

  1. 内存大小的基本单位是字节,但cpu并不是逐字节读写内存,而是以2,4或8的倍数的字节块来读写内存。因此,就会对基本数据类型的地址做出一些限制,即它的地址必须是2,4或8的倍数,要求他们按照这个规则排列,这就是对齐。
  2. 有些平台每次读都是从偶地址开始,如果一个int型(假设为32位系统)如果存放在偶地址开始的地方,那么一个读周期就可以读出这32bit,而如果存放在奇地址开始的地方,就需要2个读周期,并对两次读出的结果的高低字节进行拼凑才能得到该32bit 数据。显然在读取效率上下降很多。
  3. 不同的平台对齐方式可能不同,这就导致同样的结构在不同的平台大小可能不一样,互相发送的数据可能出现错乱。

结构体和联合体的区别

联合体和结构体有相同之处,但两者有本质的不同。
结构体中,各成员有各自的内存空间;
而联合体的成员共用一块内存,这块内存的大小是各成员中最大类型所占的字节大小。

这里说的共享不是指把多个成员同时装入一个联合体变量内,而是指该联合变量可被赋予任一成员值,每次只能赋一种值,赋入新值会冲去旧值。

示例:

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

union node2
{
	char a;
	int b;
	double c;
};
int main(void)
{
	struct node S1;
	union node2 S2;
	printf("size of S1 is %d\n", sizeof(S1));
	printf("sizeof S2 is %d\n", sizeof(S2));
	return 0;
}

在这里插入图片描述

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_索伦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值