C语言学习(14)-联合体和枚举
目录
1. 联合体
1. 联合体的定义
1.2 联合体的特点
1.3 相同成员的结构体和联合体对比
1.4 联合体使用示例
1.5 使用联合体判断大小端存储
2. enum枚举
2.1 枚举类型的声明
2.2 枚举变量的定义
2.3 枚举类型的优点
联合体是一种特殊的数据类型,像结构体一样,联合体也是由一个或多个成员构成,这些成员可以是不同的类型。但是编译器只为最大的成员分配足够的内存空间。联合体的特点是所有成员共用同一块内存空间。所以联合体也叫:共用体。
1. 联合体
1. 联合体的定义
为了定义联合体,需要使用 union 语句,方式与定义结构体类似。union 语句定义了一个新的数据类型,带有多个成员。union 语句的格式如下:
union [union tag]
{member definition;member definition;...member definition;
} [one or more union variables];
union tag 是可选的,每个 member definition 是标准的变量定义,比如 int i; 或者 float f; 或者其他有效的变量定义。在共用体定义的末尾,最后一个分号之前,您可以指定一个或多个共用体变量,这是可选的。下面定义一个名为 Data 的共用体类型,有三个成员 i、f 和 str:
union Data
{int i;float f;char str[20];
} data;
1.2 联合体的特点
联合的成员是共用同一块内存空间的,这样一个联合变量的大小,至少是最大成员的大小(因为联合体至少要有能力保存最大的那个成员)。
下面的代码展示了这一特点:
//代码1
#include <stdio.h>
//联合类型的声明
union Un
{char c;int i;
};
int main()
{//联合变量的定义union Un un = { 0 };// 下面输出的结果是一样的吗?printf("%p\n", &(un.i));printf("%p\n", &(un.c));printf("%p\n", &un);return 0;
}//代码2
#include <stdio.h>
//联合类型的声明
union Un
{char c;int i;
};
int main()
{//联合变量的定义union Un un = { 0 };un.i = 0x11223344;un.c = 0x55;printf("%x\n", un.i);return 0;
}
输出的结果分别是:
代码1:
001AF85C
001AF85C
001AF85C代码2:
11223355
代码1输出的三个地址一模一样,代码2的输出,我们发现将i的第4个字节的内容修改为55了。
我们仔细分析就可以画出,un的内存布局图;因为最后赋值给变量的值占用了内存位置。

1.3 相同成员的结构体和联合体对比
//结构体
struct S
{char c;int i;
};struct S s = {0};//联合体
union Un
{char c;int i;
};union Un un = {0};
结构体和联合体的内存对比:

1.4 联合体使用示例
使用联合体是可以节省空间的,举例:
比如,我们要搞一个活动,要上线一个礼品兑换单,礼品兑换单中有三种商品:图书、杯子、衬衫。
每一种商品都有:库存量、价格、商品类型和商品类型相关的其他信息。
图书:书名、作者、页数
杯子:设计
衬衫:设计、可选颜色、可选尺寸
如果直接使用结构体:
struct gift_list
{//公共属性int stock_number;//库存量double price; //定价int item_type;//商品类型//特殊属性char title[20];//书名char author[20];//作者int num_pages;//页数char design[30];//设计int colors;//颜色int sizes;//尺寸
};
使用结构体确实很简单方便,但是结构体的设计中包含了所有礼品的各种属性,这样使得结构体的大小就会偏大,比较浪费内存。因为只有部分属性信息是常用的。比如:
商品是图书的时候,就不需要别的商品的属性,所以我们把公共属性单独写出来,属于各种商品本身的属性使用联合体,这样就可以节省内存空间。
struct gift_list
{int stock_number;//库存量double price; //定价int item_type;//商品类型union {struct{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;
};
1.5 使用联合体判断大小端存储
写一个程序,判断当前机器是大端?还是小端?
int check_sys()
{union{int i;char c;}un;un.i = 1;return un.c;//返回1是小端,返回0是大端
}
巧妙利用了联合体共用统一内存的特性,进而判定大小端存储模式。
2. enum枚举
2.1 枚举类型的声明
枚举是 C 语言中的一种基本数据类型,用于定义一组具有离散值的常量,它可以让数据更简洁,更易读。
枚举类型通常用于为程序中的一组相关的常量取名字,以便于程序的可读性和维护性。
定义一个枚举类型,需要使用 enum 关键字,后面跟着枚举类型的名称,以及用大括号 {} 括起来的一组枚举常量。每个枚举常量可以用一个标识符来表示,也可以为它们指定一个整数值,如果没有指定,那么默认从 0 开始递增。
枚举语法定义格式为:
enum 枚举名 {枚举元素1,枚举元素2,……};
接下来我们举个例子,比如:一星期有 7 天,如果不用枚举,我们需要使用 #define 来为每个整数定义一个别名:
#define MON 1
#define TUE 2
#define WED 3
#define THU 4
#define FRI 5
#define SAT 6
#define SUN 7
接下来看看使用枚举的方式:
enum DAY
{MON=1, TUE, WED, THU, FRI, SAT, SUN
};
注意:第一个枚举成员的默认值为整型的 0,后续枚举成员的值在前一个成员上加 1。我们在这个实例中把第一个枚举成员的值定义为 1,第二个就为 2,以此类推。
可以在定义枚举类型时改变枚举元素的值,没有指定值的枚举元素,其值为前一元素加 1。
2.2 枚举变量的定义
前面我们只是声明了枚举类型,接下来我们看看如何定义枚举变量。
我们可以通过以下三种方式来定义枚举变量:
- 先定义枚举类型,再定义枚举变量
enum DAY {MON=1, TUE, WED, THU, FRI, SAT, SUN }; enum DAY day; - 定义枚举类型的同时定义枚举变量
enum DAY {MON=1, TUE, WED, THU, FRI, SAT, SUN } day; - 省略枚举名称,直接定义枚举变量
enum {MON=1, TUE, WED, THU, FRI, SAT, SUN } day;
2.3 枚举类型的优点
- 增加代码的可读性和可维护性
- 和#define定义的标识符比较枚举有类型检查,更加严谨。
- 便于调试,预处理阶段会删除#define 定义的符号
- 使用方便,一次可以定义多个常量
- 枚举常量是遵循作用域规则的,枚举声明在函数内,只能在函数内使用
