C 语言Union 结构

有时需要一种数据结构,不同的场合表示不同的数据类型。比如,如果只用一种数据结构表示水果的"量",这种结构就需要有时是整数(6个苹果),有时是浮点数(1.5公斤草莓)。

C 语言提供了 Union 结构,用来自定义可以灵活变更的数据结构。它内部包含各种属性,但是所有属性共用一块内存,导致这些属性都是对同一个二进制数据的解读,其中往往只有一个属性的解读是有意义的。并且,后面写入的属性会覆盖前面的属性,这意味着同一块内存,可以先供某一个属性使用,然后再供另一个属性使用。这样做的最大好处是节省内存空间。

objectivec 复制代码
union quantity {
  short count;
  float weight;
  float volume;
};

上面示例中,union命令定义了一个包含三个属性的数据类型quantity。虽然包含三个属性,但是只能写入一个值,三个属性都是对这个值的不同解读。最后赋值的属性,往往就是可以取到有意义的值的那个属性。

使用时,声明一个该类型的变量。

objectivec 复制代码
// 写法一
union quantity q;
q.count = 4;

// 写法二
union quantity q = {.count=4};

// 写法三
union quantity q = {4};

上面代码展示了为 Union 结构赋值的三种写法。最后一种写法不指定属性名,就会赋值给第一个属性。

执行完上面的代码以后,q.count可以取到值,另外两个属性取不到值。

objectivec 复制代码
printf("count is %i\n", q.count); // count is 4
printf("weight is %f\n", q.weight); // 未定义行为

如果要让q.weight属性可以取到值,就要先为它赋值。

objectivec 复制代码
q.weight = 0.5;
printf("weight is %f\n", q.weight); // weight is 0.5

一旦为其他属性赋值,原先可以取到值的q.count属性就跟着改变,使用它可能就没有意义了。除了这一点,Union 结构的其他用法与 Struct 结构,基本上是一致的。

Union 结构也支持指针运算符->

objectivec 复制代码
union quantity {
  short count;
  float weight;
  float volume;
};

union quantity q;
q.count = 4;

union quantity* ptr;
ptr = &q;

printf("%d\n", ptr->count); // 4

上面示例中,ptrq的指针,那么ptr->count等同于q.count

Union 结构指针与它的属性有关,当前正在按照哪个属性解读数据,它的指针就是对应的数据类型。

objectivec 复制代码
union foo {
  int a;
  float b;
} x;

int* foo_int_p = (int *)&x;
float* foo_float_p = (float *)&x;

x.a = 12;
printf("%d\n", x.a);           // 12
printf("%d\n", *foo_int_p);    // 12

x.b = 3.141592;
printf("%f\n", x.b);           // 3.141592
printf("%f\n", *foo_float_p);  // 3.141592

上面示例中,&x是 foo 结构的指针,它的数据类型完全由当前赋值的属性决定。

typedef 命令可以为 Union 数据类型起别名。

objectivec 复制代码
typedef union {
  short count;
  float weight;
  float volume;
} quantity;

上面示例中,union命令定义了一个包含三个属性的数据类型,typedef命令为它起别名为quantity

Union 结构的好处,主要是节省空间。它将一段内存空间,重用于不同类型的数据。定义了三个属性,但同一时间只用到一个,使用 Union 结构就可以节省另外两个属性的空间。Union 结构占用的内存长度,等于它内部最长属性的长度。

相关推荐
sprintzer18 小时前
12.06-12.15力扣分治法刷题
算法·leetcode
老毛肚18 小时前
登录架构设计
java·开发语言
月明长歌18 小时前
【码道初阶】【牛客BM30】二叉搜索树与双向链表:java中以引用代指针操作的艺术与陷阱
java·数据结构·算法·leetcode·二叉树·笔试·字节跳动
南棱笑笑生18 小时前
20251215给飞凌OK3588-C开发板适配Rockchip原厂的Buildroot【linux-6.1】系统时统计eth1的插拔次数
linux·c语言·开发语言·rockchip
YJlio18 小时前
桌面工具学习笔记(11.4):BgInfo + Desktops + ZoomIt 组合拳——演示与排障环境一键到位
笔记·学习·自动化
hoiii18718 小时前
使用RPCA算法对图像进行稀疏低秩分解
人工智能·算法
yuuki23323318 小时前
【C++】内存管理
java·c++·算法
玩具猴_wjh18 小时前
12.15 学习笔记
笔记·学习
shenghaide_jiahu18 小时前
数学分析简明教程——6.3
学习
消失的旧时光-194318 小时前
Java 线程池(第四篇):ScheduledThreadPoolExecutor 原理与定时任务执行机制全解析
java·开发语言