
像结构体一样,联合体也是由一个或者多个成员构成,这些成员可以是不同的类型。
在联合体里编译器只为最大的成员分配足够的内存空间,所以联合体的特点是所有成员共用同一块内存空间,所以联合体也叫:共用体。
给联合体其中一个成员赋值,其他成员的值也跟着变化。

所以联合体一般所占用的空间也更小
联合的成员是共用同一块内存空间的,这样一个联合变量的大小,至少是最大成员的大小(因为联合体至少得有能力保存最大的那个成员)。
这里具体再看一下联合体及成员的内存是怎么分配的

这里输出的三个地址一模一样,其un的内存布局如下图:

还可用下面的例子验证其存储原理

这里确实开辟了四个字节的空间


这里改了c的值,连同i一起改了,验证了联合的成员是共用同一块内存空间的,这就是联合体与结构体的本质区别,结构体是给每个成员分配一块空间的。
struct S
{
char c;
int i;
};
struct S s = { 0 };union Un
{
char c;
int i;
};
union Un un = { 0 };联合体和结构体内存布局情况:

所以联合体和结构体的使用情景是不同的

按照第一点,Un1的大小应该是5个字节,Un2的大小应该是14个字节,出现这样的结果就涉及到第二点了
首先,数组在计算对齐数时,是按照元素来算的,数据类型为char,自身的大小为1,vs上默认对齐数为8,最终对齐数取较小值为1,这又涉及我上一篇关于对齐数的解析了深入解析自定义类型:结构体与位段 所以Un1的最大成员大小为5,不是最大对齐数4的整数倍,所以要对齐最大对齐数的整数倍,所以联合体大小为4的倍数,8,相当于浪费了3个空间用于对齐。
对于Un2也一样分析,数组的数据类型为short,自身大小为2,vs默认对齐数为8,最终对齐数取较小值2,i的数据类型为int,自身大小为4,小于vs默认对齐数8,所以i的最终对齐数为4 Un2的最大成员大小为14不是最大对齐数4的对数,所以联合体大小为16,浪费2个空间用于对齐。
使用联合体是可以节省空间的,如下例: 现在商场要搞一个活动,要上线一个礼品兑换单,礼品兑换单中有三种商品:图书、杯子、衬衫。 每一种商品都有:库存量、价格、商品类型和商品类型相关的其他信息
总结下来就是下图:

单用结构体的话,写出来的程序就如下图

上述结构体构想的时候很简单,用起来也很方便,但是结构的设计包含了所有礼品的各种属性,图中红框成员在对应商品上就没有用上,这样就使得结构体的大小就会偏大,比较浪费内存。因为对于礼品兑换单中的商品来说,只有部分属性信息是常用的。 比如: 商品是图书,就不需要设计,可选颜色,可选尺寸了。
所以可以把公共属性单独写出来,剩余属于各种商品本身的属性使用联合起来。这样就可以介绍所需的内存空间,一定程度上节省了内存。
struct gift_list
{
int stock_number;//库存量
double price;//定价
int item_type;//商品类型
union {//结构体可以匿名,联合体也可以
struct
//这里3个匿名结构体创建的成员不一样,所以是三个单独的匿名结构体类型
//所以符合匿名结构体只能使用一次的规则
//这三个结构体变量不会同时存在,礼品之中三选一
//所以这三者可以共用一片空间了
{
char title[20];//书名
char author[20];//作者
int num_pages;//页数
}book;
struct
{
char design[30];//设计
}mug;//杯子
struct
{
char design[30];//设计
int colors;//颜色
int sizes;//尺寸
}shirt;
}item;
};union item:根据item_type的值,存储对应类型的礼品详细信息 共用体的特点是所有成员共享同一块内存空间,因此item的大小取决于其最大成员。这里最大的成员是shirt结构体(30+4+4=38 字节),所以item占用 38 字节。 item(38 字节,但需对齐到 4 的倍数,故为 40 字节)
深入解析数据在内存中的存储 - 大小端字节序和字节序判断(百度笔试题) 在上面这篇文章是这样写的

这里使用联合体的知识进行改进

顾名思义枚举的意思就是一一列举,把可能的取值一一列举出来,例如:
用代码表示如下:
enum Day//星期
{
Mon,
Tues,
Wed,
Thur,
Fri,
Sat,
Sun
};
enum Sex//性别
{
MALE,
FEMALE,
SECRET
};
enum Color//颜色
{
RED,
GREEN,
BLUE
};

之前已经知道了#define定义常量,这里为什么还要会枚举呢? 枚举的优点:
//模拟实现简单计算器
#include<stdio.h>
void menu()
{
printf("*************************\n");
printf("***** 1.add 2. sub *****\n");
printf("***** 3.mul 4. div *****\n");
printf("***** 0.exit *****\n");
printf("*************************\n");
}
int main()
{
int input = 0;
do
{
menu();
printf("请选择:");
scanf("%d", &input);
switch (input)
{
case 1:
break;
case 2:
break;
case 3:
break;
case 4:
break;
case 0:
break;
default:
break;
}
} while (input);
return 0;
}这个不是很直观,但可以看出还是有一些可读性改进的。
#include<stdio.h>
enum Option
{
EXIT,
ADD,
SUB,
MUL,
DIV
};
//模拟实现简单计算器
void menu()
{
printf("*************************\n");
printf("***** 1.add 2. sub *****\n");
printf("***** 3.mul 4. div *****\n");
printf("***** 0.exit *****\n");
printf("*************************\n");
}
int main()
{
int input = 0;
do
{
menu();
printf("请选择:");
scanf("%d", &input);
switch (input)
{
case ADD:
break;
case SUB:
break;
case MUL:
break;
case DIV:
break;
case EXIT:
break;
default:
break;
}
} while (input);
return 0;
}
这里8是int类型,s是Sex类型,把s = FEMALE改为s = 8。在C语言下可以运行,在C++下就不能运行了

所以不同语言对语法检测的严格程度是不同的,C++对语法的检测非常严格。

#define定义的MALE在编译时就将MALE全部替换为5,调试时的代码MALE与看到的代码5不是一回事。
以上就是联合体与枚举部分的全部内容了,说实话我感觉枚举的用处不大,但老师说以后工作会感受到它的具体用处,还有明天考科三,希望过。