联合体(union)以及数据的存储

联合体(union)以及数据的存储

当多个数据需要共享内存或多个数据每次只取其一时,可以利用联合体(union),有关联合体的描述如下:
1.联合体是一个结构;
2.它的所有成员相对于基地址的偏移量都为0;
3.此结构空间要大到足够容纳最"宽"的成员;
4.其对齐方式要适合其中所有的成员。

对上面四句话的理解:
        由于联合体的所有成员是共享一段内存的,因此每个成员的存放首地址相对于联合体变量的基地址额偏移量为0,即所有成员的首地址都是一样的。为了使得所有成员能够共享一段内存,因此该空间必须足够容纳这些成员中最宽的成员。再来着重介绍一下什么叫"对其方式要适合其中所有的成员"?

例如:
#include<stdio.h>
typedef struct u
{
	char a;
	int b;
}U1;

int main()
{
	printf("%d\n",sizeof(U1));
	return 0;
}


假设U1按如下方式内存方式布局(内存地址从左至右递增):



       因为U1中有最强对齐要求的是b字段(int),所以U1对象的首地址一定是4的倍数,那么上述内存的布局中的b字段能满足int类型的对齐要求吗?显然是不能的,于是有了如下的地址分配方案:



       这个方案在a与b之间多分配了3个填充(padding)字节,这样当整个struct对象首地址满足4字节的对齐要求时,b字段也一定能满足int型的4字节对齐规定。那么sizeof(U1)显然就应该是8,而b字段相对于结构体首地址的便宜就是4。我们看一下程序给的结果吧:


那么下面这个呢?
typedef struct u2
{
      int     a;
      char  b;
}U2;

其实和上例子是一样的,sizeof(U2)也是8。


好的,现在你已经掌握了结构体内存布局的基本准则,尝试分析一个稍微复杂点的类型吧。
例如:
typedef struct u
{
	char a[9];
	int b;
	double d;
}U1;
      先来分析一下,a占9字节,b占4字节,d占8字节,这里最"宽"的变量是a,因此内存大小至少是9。像上面的例子一样,U1的地址最前面是9个字节,然后在a和b之间多分配了3个填充(padding)字节,在然后是b的4个字节,最后是d的8个字节。sizeof(U1)=24。看看程序运行的结果吧:
#include<stdio.h>
typedef struct u
{
	char a[9];
	int b;
	double d;
}U1;

int main()
{
	printf("%d\n",sizeof(U1));
	return 0;
}



下面来个有关union使用的测试程序加深理解:
#include<stdio.h>
union un
{
	int i;
	short int si[2];
	char c[4];
}u;

int main()
{
	u.c[0]='A';
	u.c[1]='B';
	u.c[2]='C';
	u.c[3]='D';
	printf("u.c[0]=%d,u.c[1]=%d,u.c[2]=%d,u.c[3]=%d\n",u.c[0],u.c[1],u.c[2],u.c[3]);
	printf("u.si[0]=%d,u.si[1]=%d\n",u.si[0],u.si[1]);
	printf("u.i=%d\n",u.i);
	return 0;
}

程序运行结果如下:


在程序中,由于联合体的特点,变量x占4个字节。我们可以从3个角度观察这4个字节:
(1)整体看,是一个int型数据;
2)分成2部分看,是两个短整型数据;
(3)分成4部分看,是4个单字节的数据。
但无论怎么看,就是这4个字节。无论用哪种形式操作数据,使用的也就是这4个字节。联合体为我们提供了从不同的角度使用这4个字节的方式。
x.c[0]到x.c[3]的值分别为65\66\67\68,这好理解。
x,si[0]占2字节,与x.c[0]和x.c[1]相同。验证一下:16961=66*256+65(66是'B'的ASCII值,65是'A'的ASCII值,是字符的存储形式)。注意,这里体现存储数据时低位在前,高位在后,低位是65,高位时66。正如十进制数98,高位时9,低位是8,所以98=9*10+8一样。因为是高位,所以乘以权位10,表示9这个符号代表的其实是90。66*256,因为存储66('B')的那一个字节的位置,比存储65('A')的那一字节的位置高8位,所以乘以2的8次方,即256。
       概括讲,存储2字节的16961时,其低8位,是65,在前(x.c[0]),而其高8位,是66,在(x.c[1])。低位在前,高位在后。
       请自行验证:17475=68*256+67,提现低位在前,高位在后。(x.si[1]占2字节,与x.c[2]和x.c[3]相同)。
       再请验证:1145258561=17475*256*256+16961,也体现在低位在前,高位在后。(x.i占4字节,与x.si[0]和x.si[1]相同)。
       再请验证:1145258561=68*256*256*256+67*256*256+66*256+65。同样的道理。

  • 8
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在C语言中,union是一种特殊的数据类型,可以在同一个内存位置存储不同类型的数据union中的成员共用同一块内存空间,所以union变量在内存中占用的字节数取决于成员中占用空间最大的成员。 为了使得所有成员能够共享一段内存,该空间必须足够容纳成员中最宽的成员。同时,对齐方式也必须适合其中所有的成员,符合成员的自身对齐方式。 例如,如果一个union成员中包含了一个long类型的变量和一个int类型的变量,那么这个union变量在内存中将占用8个字节,因为long类型在一般平台上占用8个字节,而int类型只占用4个字节。 在使用union时,可以定义多个成员,但是同一时间只能有一个成员包含有效值。这意味着在给定的时刻,只有一个成员可以被访问和使用。 这种特性使得union可以用于一些需要在不同类型之间进行转换的情况,例如在网络编程中,可以使用union将网络字节序和主机字节序进行转换。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [C语言编程中的联合体union入门学习教程](https://download.csdn.net/download/weixin_38618140/14913941)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [struct、union数据存储及区别](https://blog.csdn.net/qq_62129885/article/details/127993733)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值