前言
在上一篇文章中,小编将结构体的学习笔记整理出来了。现在,小编将枚举和联合体笔记分享给大家。枚举和联合体与结构体一样,都是自定义类型,在学习完枚举和联合体后,C语言中自定义类型也就告一段落啦。
联合体
概述
联合体也是自定义类型,关键字为union,特点是所有成员共⽤同⼀块内存空间,因此,联合体也叫做共用体。
声明
union U { char c; char i; };
code
#include<stdio.h> union U { char c; int i; }; int main() { union U u = { 0 }; printf("%d\n", sizeof(u)); return 0; }
联合体的特点
code
#include<stdio.h> union U { char c; int i; }; int main() { union U u = { 0 }; printf("%d\n", sizeof(u)); printf("%p\n", &u); printf("%p\n", &(u.i)); printf("%p\n", &(u.c)); return 0; }
运行结果
4 008FFADC 008FFADC 008FFADC
分析
i和共用了一个空间,没有给i单独开一个空间,也没有给c单独开一个空间。
因此,这个叫做联合体(共用体)。
编译器只为最⼤的成员分配⾜够的内存空间,起码得保证最大的有空间容下。
code
#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; }
运行结果
11223355
分析
联合体大小的计算
• 联合的⼤⼩⾄少是最⼤成员的⼤⼩。
• 当最⼤成员⼤⼩不是最⼤对⻬数的整数倍的时候,就要对⻬到最⼤对⻬数的整数倍。
code
#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; }
运行结果
8 16
分析
对Un1:
这里,我们第一反应可能认为大小为5,因为c的字节是最大的,为5。
但是我们忽略可第二个规则“当最⼤成员⼤⼩不是最⼤对⻬数的整数倍的时候,就要对⻬到最⼤对⻬数的整数倍。”
这里的c数组是char型,自身大小是1,vs默认对齐数是8,故数组c的大小为1
i是int型,vs默认对齐数是8,故i的大小是4
联合的最大对齐数是4,最大成员是5,显然5不是4的倍数
5后面只有8是4的倍数
因此,输出结果为8
对Un2:
一个short类型是2个字节,现在有7个,那么一共14个字节
联合体中最大成员是14,最大对齐数是4,显然14不是4的倍数
14后面6是4的倍数
因此,输出结果为16
总结:
联合体大小不是最大成员的大小
优点
使用联合体可以节省一定的空间
HAUE某学院学生会需举办活动,要上线⼀个礼品兑换单,礼品兑换单中有三种商品:图书、杯⼦、衬衫。
每⼀种商品都有:库存量、价格、商品类型和商品类型相关的其他信息。
图书:书名、作者、页数
图书:书名、作者、页数
杯子:设计
杯子:设计
衬衫:设计、可选颜色、可选尺寸
衬衫:设计、可选颜色、可选尺寸
结构其实设计的很简单,⽤起来也⽅便,但是结构的设计中包含了所有礼品的各种属性,这样使得结构体的⼤⼩就会偏⼤,⽐较浪费内存。因为对于礼品兑换单中的商品来说,只有部分属性信息是常⽤的。
使用联合体:
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; };
虽然写起来有点麻烦,但是节省了一定的空间
练习
用联合体写⼀个程序,判断当前机器是⼤端?还是⼩端?
union Un { char c; int i; }; int main() { union Un un; un.i = 1; if (un.c == 1) { printf("小端\n"); } else { printf("大端\n"); } return 0; }
枚举
概述
枚举,顾名思义,列举
将有限个,一 一列举出来,这就是枚举类型
声明
enum Day//星期 { Mon, Tues, Wed, Thur, Fri, Sat, Sun }; enum Sex//性别 { MALE, FEMALE, SECRET };
这些可能取值都是有值的,默认从0开始,依次递增1,当然在声明枚举类型的时候也可以赋初值。
enum Sex//性别 { MALE=3, FEMALE=5, SECRET=7 };
优点
- 增加代码的可读性和可维护性
- 和#define定义的标识符⽐较枚举有类型检查,更加严谨。
- 便于调试,预处理阶段会删除 #define 定义的符号
- 使⽤⽅便,⼀次可以定义多个常量
- 枚举常量是遵循作⽤域规则的,枚举声明在函数内,只能在函数内使⽤
使用
enum Color//颜色 { RED=1, GREEN=2, BLUE=4 }; enum Color clr = GREEN;//只能拿枚举常量给枚举变量赋值,才不会出现类型的差异。 clr = 5;//避免这样写
可以拿整数给枚举变量赋值呢?
在C语⾔中是可以的,但是在C++是不⾏的,C++的类型检查⽐较严格。