前言
前面我们学习了一种自定义类型,结构体,现在我们学习另外两种自定义类型,联合和 枚举。
目录
一、联合体
-
联合体类型的声明
-
联合体的特点
-
相同成员联合体和结构体对比
-
联合体大小的计算
-
用联合体判断当前机器大小端
二、枚举
-
枚举类型的声明
-
枚举类型的优点
-
枚举类型的使用
正文开始------
一、联合体
1. 联合体类型的声明
与结构体一样,联合体是由一个或多个成员构成,这些成员可以是不同的类型。
cs
#include<stdio.h>
//联合体类型的声明 union是关键字
union Un
{
char c;
int i;
};
int main()
{
//联合体变量的定义
union Un un={0};
//计算联合体变量的大小
printf("%zd\n",sizeof(un));
return 0;
}
2. 联合体类型的特点
联合的成员是共用一块内存空间的(所以联合体也叫共用体),所以联合变量的大小至少是最大成员的大小,因为联合体至少得有能力保存最大的那个成员。
代码 1 及其运行结果
cs
#include<stdio.h>
//联合类型的声明
union Un
{
char c;
int i;
};
int main()
{
union Un un={0};
printf("%p\n",&(un.c));
printf("%p\n",&(un.i));
printf("%p\n",&un);
return 0;
}
代码 2 及其运行结果
cs
#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;
}
图解见下:
i 和 c 共用一块内存空间,所以联合体也叫共用体,同一时间只能使用 i 和 c 中的一个。
3. 相同成员的结构体和联合体对比
我们再对比一下相同成员的结构体和联合体的内存布局情况。
cs
struct S
{
char c;
int i;
};
struct S s={0};
cs
union Un
{
char c;
int i;
};
union Un un={0};
4. 联合体大小的计算
- 联合体的大小至少是最大成员的大小。
- 当最大成员的大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍。
cs
#include<stdio.h>
union Un1
{
char c[5];
int i;
};
union Un2
{
short c[7];
int i;
};
int main()
{
printf("%zd\n",sizeof(union Un1));
printf("%zd\n",sizeof(union Un2));
return 0;
}
计算一个数组的大小,就是这个数组类型大小 * 数组成员个数
【例如】
short [7],2*7=14。
对于 union Un2,我们来计算,首先最大成员的大小是14,最大对齐数为 4,但是14不是最大对齐数的整数倍,那就要对齐到最大对齐数的整数倍,即为16。union Un1同理。
我们发现,对于同样成员的结构体和联合体,联合体有时会占用更少的内存,可以节省空间。
下面我们举个栗子,看看在什么情况下适用联合体。
我们要搞一个活动,要上线一个礼品兑换单,礼品兑换单中有三种商品:图书、杯子、衬衫。每种商品都有:库存量、价格、商品类型和商品类型相关的其他信息。
图书:书名、作者、页数
杯子:设计
衬衫:设计、可选颜色、可选尺寸
以结构体的的方式写
cs
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; //尺寸
};
这样的结构体设计很简单,用起来也比较方便,但是其中包含了所有的属性,这样就导致结构体的大小就会偏大,浪费内存,并且其中属性并非所有的商品都有。所以我们可以把公共的属性单独写出来,剩余属于各种商品本身的属性使用联合体,这样可以节省内存空间。
cs
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;
};
上面结构体和联合体都是匿名,因为这些类型只会被使用一次。
5. 用联合体判断当前机器大小端
写一个程序,判断当期机器是大端,还是小端。
cs
int check_sys()
{
union Un
{
char c;
int i;
};
un.i=1;
return un.c;
}
二、枚举
1. 枚举类型的声明
枚举即列举,把可能取值一一列举出来。
cs
enum Day
{
Mon;
Tues;
Wed;
Thur;
Fri;
Sat;
Sun;
};
上面定义的 enum Day 是枚举类型。{} 里面的内容是枚举类型的可能取值,也叫 枚举常量。
这些可能取值都是有值的,默认从0开始,依次递增1,在声明枚举类型的时候也可以赋初值。
cs
enum Color
{
Blue=3
Red=4;
Pink=7;
Black=9;
};
2. 枚举类型的优点
我们可以使用 #define 定义常量,为什么要使用枚举类型?
- 增加代码的可读性和可维护性;
- 和 #define 定义的标识符比较枚举有类型检查,更加严谨;
- 便于调试,预处理阶段会删除 #define 定义的符号;
- 使用方便,一次可以定义多个常量;
- 枚举常量遵循作用域规则,枚举声明在函数内,只能在函数内使用。
3. 枚举类型的使用
cs
enum Color
{
RED=3;
GREEN=6;
};
enum Color clr = GREEN; //使用枚举常量给枚举变量赋值
完------
期待我们下一次相遇------