c语言:联合体—union

本文详细介绍了联合体的基本概念、内部成员的访问方式、内存分配特点及其与大小端的关系,并通过实例帮助理解联合体的工作原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


在这里插入图片描述

一.基本认识

1.一个联合体的基本样式

在这里插入图片描述

在这里插入图片描述

看得出来其实跟我们定义结构体是一样的(如果还不大了解结构体的可以看看这篇博客什么是结构体),事实上结构体和联合体也经常混在一起使用

想要认识联合体就得从它的内部空间分配开始

我们来看一个例子

在这里插入图片描述

这里可能就发现有些不对了,一个int和一个char类型不应该是5个字节吗?为什么得出的结论却是4个字节呢?

这就引出了联合体的性质,联合体开辟空间的总大小是由最大的那个成员决定的。换言之,这里int是4个字节而char是1个字节,那么该空间大小就由int来决定,因为int更大(当然这里其实有点问题,并非它空间的大小就一定是最大成员的大小,我这里只说明一下现象)

在这里插入图片描述

相信大家都会认为这个空间大小是5,因为5最大吗,但其实并不是

在这里插入图片描述

这是怎么一回事呢?这里有点复杂直接说结论:联合体内的总大小必须能整除里面每个成员的大小,换言之int是4,char是1,而它所需最大空间又是5,那么联合体空间大小必须大于5并且能整除1和4

联合体的本质是内部所有成员共用一个空间

2.内部成员的访问

在这里插入图片描述

与结构体一样,联合体既可以通过点操作符来访问,也可以用箭头操作符通过指针来访问

3.具体的内存分配

在这里插入图片描述

这里需要了解的是每一个字节都会有地址,而我们平时使用&操作符访问的其实是一个字节的地址(最低地址)

在这里插入图片描述

而整个联合体的地址也是该地址,换句话说,联合体的地址和该联合体内最大成员的地址在数值上是一样的

在这里插入图片描述

上文已经说到该联合体是4个字节(也就是a的空间大小),那么开辟b的时候又是怎么一回事呢?

在这里插入图片描述

可以看到b的地址竟然也和a一样,其实这也不难理解,因为b和a本质上是共用一个空间的

在这里插入图片描述

每个成员使用空间都是从最大成员的最低地址开始向上呈放射性开辟(你需要多大空间就向上开辟多少字节)

得出结论:联合体内所有成员的起始地址都是一样的!!

那么可能又有疑问了,又是a开辟地址,又是b开辟地址,那么它们的地址不是重合了吗?

这就又要提到联合体的本质了,上文已经说过所有成员共用同一地址。换言之,每个成员在开辟地址时虽然都从同一地址向上开辟,但它们都认为自己是唯一的元素(可以简单理解成每一个成员都认为自己是联合体内第一元素),这是联合体的性质

二.大小端对联合体的影响

在这里插入图片描述在这里插入图片描述

首先在这里普及一下大小端的概念,将低权重数字放在低地址就是小端,将低权重数字放在高地址就是大端

在这里插入图片描述

这里通过我们的内存监视可以看到,VS将权重低的数字(44)放在了高地址处,所有VS是使用的小端存放

好,进行完前置工作后,我们来看下一段代码

在这里插入图片描述

可以看到我们通过这一段代码可以不用通过内存监视直接判断编译器是大端还是小端,它究竟是怎么做到的呢?接下来一一解析

首先要了解的是int是4个字节32个比特位,那么1在内存中应当是31个0+最后一个1

在这里插入图片描述在这里插入图片描述

b是char类型,只有1个字节,而根据上文联合体的空间起始地址都是一样的。那么可以知道b所开辟的空间永远是在最低地址。而又因为我们并未给b赋值,所以b一直是a用“剩下的”。换言之,如果是大端,那么b的值就是0;如果是小端,那么b的值就是1

如果理解了上面的演示,那么相信就能明白为什么联合体可以用来判断编译器是大端还是小端啦

三.一个问题

在这里插入图片描述

这个程序打印出来的是什么呢?

在这里插入图片描述

接下来进行解析

p=&u是让*p指向该联合体。p->a[0]=0x36,是指将a[0]赋值为16进制的36。p->i是说明我们打印的是i的值,打印i的值就是将这4个字节当成一个整体来访问,如下图我们用数组将每个字节分别赋值,但我们直接打印一个整体(也就是4个字节)

在这里插入图片描述

而我们的VS是小端,低权值数字放在低地址处,那么我们拿出来低地址的数据就该放到最后,也就是39放到最后。那么我们由下依次向上读取,最终就打印出来36373839啦

在这里插入图片描述

评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

咸蛋挞

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

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

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

打赏作者

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

抵扣说明:

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

余额充值