该系列为本人的学习笔记,主要由本人整理书写而成。部分内容来自教材、视频课程等,不能保证完全原创性。
萌新的学习笔记,写错了恳请斧正。
# 联合体(共用体)
联合体和结构体类似,也由一个或多个成员构成
但是联合体的特殊之处在于编译器只为成员中宽度最大的成员分配足够的内存空间
其余的所有成员都共用同一片空间,所以联合体也被称为共用体
这也就导致了如果给其中一个成员赋值,其他成员的值也会跟着变化
# 联合体的声明
联合体的声明和结构体类似,比方说:
union U1 | |
{ | |
char c; | |
int n; | |
}; | |
union U2 | |
{ | |
char c; | |
int n; | |
} u; | |
union U3 | |
{ | |
char c; | |
int n; | |
} u = {.c = 'a'}; | |
union U4 | |
{ | |
char c; | |
int n; | |
} u = {99}; | |
typedef union U5 | |
{ | |
char c; | |
int n; | |
} UU; |
# 联合体的特点
联合体的大小至少是其中最宽成员的大小,比方说下面这段代码的结果是 4:
#include <stdio.h> | |
union Un | |
{ | |
char c; | |
int i; | |
}; | |
int main() | |
{ | |
union Un un = { 0 }; | |
printf("%d\n", sizeof(un)); | |
return 0; | |
} |
联合体空间共用,占有内存的同一片空间,比方说下面代码在小端机器的输出为 11223355:
#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; | |
} |
# 联合体的大小
但是联合体的大小也是存在内存对齐的
如果最大成员大小不是最大对齐数的整数倍的时候,就会对齐到最大对齐数的整数倍
比方说,下面程序的输出结果为 8 16:
#include <stdio.h> | |
union Un1 | |
{ | |
char c[5]; | |
int i; | |
}; | |
union Un2 | |
{ | |
short c[7]; | |
int i; | |
}; | |
int main() | |
{ | |
printf("%d\n", sizeof(union Un1)); | |
printf("%d\n", sizeof(union Un2)); | |
return 0; | |
} |
使用联合体可以在部分情况下节省空间。
比方说,如果一些物品(包括书、杯子、衬衫)都拥有价格、数量等信息。而其中每一类物品又有各自的分类信息(如书有书名、作者、页数等信息)。
这个时候我们可以写出这样的结构体类型(结构体联合体嵌套后面会深入讲讲):
struct item | |
{ | |
// 公共属性 | |
int number; // 数量 | |
double price; // 定价 | |
int type; // 类型 | |
// 私有属性 | |
union | |
{ | |
struct | |
{ | |
char title[20]; // 书名 | |
char author[20]; // 作者 | |
int pages; // ⻚数 | |
} book; | |
struct | |
{ | |
char design[30]; // 设计 | |
} cup; | |
struct | |
{ | |
char design[30]; // 设计 | |
int colors; // 颜⾊ | |
int sizes; // 尺⼨ | |
} shirt; | |
} item; | |
}; |
# 枚举类型
枚举类型,顾名思义,就是一一列举的类型。
枚举是 C 语言的一种定义整型常量的方法,其声明方法与结构体 / 联合体类似:
enum Sex | |
{ | |
MALE, //0 | |
FEMALE, //1 | |
OTHER //2 | |
}; | |
enum Color | |
{ | |
RED = 4, | |
GREEN = 2, | |
BLUE = 1 | |
}; | |
enum Day | |
{ | |
MON, //0 | |
TUE, //1 | |
SAT = 114, //114 | |
THU = 514, //514 | |
FRI = 8, //8 | |
SAT, //9 | |
SUN //10 | |
}; |
注意:与结构体、联合体不同,花括号中的成员以逗号分割,最后一个成员后无逗号
上面的 enum Sex、enum Color 就是定义的两个枚举类型,而花括号里面则是枚举类型的可能取值,也就是枚举常量
我们看到,枚举常量可以在定义时直接赋值为我们需要的整型常数值,也可以留空。如果留空,则其值为上一个数的值加一;如果第一个值留空则默认赋值为 0
# 枚举类型的使用
枚举类型中的枚举常量可以直接拿来当整型常量数字使用,比方说:
#include <stdio.h> | |
enum Color | |
{ | |
RED = 4, | |
GREEN = 2, | |
BLUE = 1 | |
}; | |
int main() | |
{ | |
int a = GREEN; | |
printf("%d = %d\n", a, GREEN); | |
return 0; | |
} |
我们还可以用声明过了的枚举常量创建枚举变量或其指针,枚举变量的取值范围为其类型的所有枚举常量值。创建方法与结构体 / 联合体相同(可以声明时创建也可以后面创建):
#include <stdio.h> | |
int main() | |
{ | |
enum ENUM_A | |
{ | |
X1, | |
Y1, | |
Z1 = 255, | |
A1, | |
B1, | |
} enumB = B1, * penmB = &enumB; | |
enum ENUM_A enumA = Y1; | |
printf("%d %d\n", enumA, enumB); | |
return 0; | |
} |
给枚举变量赋值时我们尽量使用对应枚举常量的标识符,不要直接使用数字
比方说,上面代码给 enumA 初始化为 Y1,而不是写成初始化为 1
其实在 C 语言中,如果使用数字赋值也是可以的,因为 C 语言的类型检查不严格,而在 C++ 这样类型检查严格的情况下就会报错。所以我们养成良好的习惯就不要写成数字赋值了
# 枚举类型的优点
我们可以用预处理命令 #define 定义标识符常量,那为什么还要使用枚举类型呢?
- 增强代码的可读性和可维护性
- 枚举类型有类型检查更严谨
- 便于调试,标识符常量在预处理的时候就被全部直接替换为数字不便于调试
- 使用方便,可以一次性定义多个常量
- 遵循作用域规则