【C语言】自定义类型:联合和枚举

前言
自定义类型有三种:结构体,联合体以及枚举。在上一篇博客中我们已经讲解了结构体,接下来我们将学习联合体和枚举。


文章目录

  • 一、联合体
    • 1.1 联合体的声明
    • 1.2 内存中的联合体成员
    • 1.3 联合体的大小计算
    • 1.4 对比联合体和结构体的内存使用情况
    • 1.5 联合的使用场景
  • 二、枚举类型
    • 2.1 枚举类型的声明
    • 2.2 枚举的优点
    • 2.3 枚举的应用场景

一、联合体

1.1 联合体的声明

联合体(Union)是一种特殊的数据结构,允许在同一内存位置存储不同的数据类型。与结构体不同,联合体的各个成员共享同一块内存空间,因此联合体的大小等于其最大成员的大小 (当最大成员大小等于最大对齐数的整数倍时) 。这意味着在联合体中只能存储一个成员的值,而不是多个成员的值。

//联合体示范
union MyUnion {
    int i;
    float f;
    char c;
};

在这个示例中,MyUnion 是一个联合体,它可以存储一个整数 i、一个浮点数 f 或一个字符 c。这些成员共享同一块内存空间,因此在任何时候只能存储其中一个成员的值。

1.2 内存中的联合体成员

联合的成员是共用⼀块内存空间的,以下几个例子来证明:

//代码1
#include 
//联合类型的声明
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;
}

运行结果:
【C语言】自定义类型:联合和枚举_第1张图片
由此可见,无论是任何一个联合体成员,还是联合体本身,它们的地址是一样的


再来看联合体成员在内存中的数据:

//代码2
#include 
//联合类型的声明
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;
}

结果如下:
【C语言】自定义类型:联合和枚举_第2张图片
当我们把16进制的11223344赋值给i,又把55赋值给c,后来我们想取出 i 时发现,其中一部分已经被c覆盖了。

当我们使用联合体时,可以看到,c和i是共用一个内存,且给un.c赋值时会覆盖掉一个字节的内容
【C语言】自定义类型:联合和枚举_第3张图片

1.3 联合体的大小计算

有以下两个条件:

  • 联合的⼤小必须大于或等于是最⼤成员的⼤⼩。
  • 联合体的大小应当是最大对齐数的整数倍

举例:

#include 
union Un1{//Un1的大小大于或等于5(5个char>1个int),又Un1的大小应当是4的整数倍,所以Un1的大小是8
	char c[5];//char大小为1,默认对齐数8,对齐数1
	int i;    //int大小为4,默认对齐数8,对齐数4
};

union Un2{//Un2的大小大于或等于14(7个short>1个int),又Un2的大小应当是4的整数倍,所以Un1的大小是16
	short c[7];//short大小为2,默认对齐数8,对齐数2
	int i;     //int大小为4,默认对齐数8,对齐数4
};

int main(){
	//下⾯输出的结果是什么?
	printf("%d\n", sizeof(union Un1));
	printf("%d\n", sizeof(union Un2));
	return 0;
}

结果如下:

【C语言】自定义类型:联合和枚举_第4张图片


1.4 对比联合体和结构体的内存使用情况

//结构体
struct S{
 char c;
 int i;
};
struct S s = {0};
//联合体
union Un{
 char c;
 int i;
};
union Un un = {0};

显而易见,联合体更加节省空间,但由于联合体的成员共用一个内存空间,所以联合体的使用是有限制的
【C语言】自定义类型:联合和枚举_第5张图片


1.5 联合的使用场景

例如,我们要搞⼀个活动,要上线⼀个礼品兑换单,礼品兑换单中有三种商品:图书、杯⼦、衬衫。每⼀种商品都有:库存量、价格、商品类型和商品类型相关的其他信息。

  • 图书:书名、作者、⻚数
  • 杯子:设计
  • 衬衫:设计、可选颜⾊、可选尺⼨
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;
};

因为每一种商品都有自己独特的属性,当我们描述一种商品时需要库存量、价格、商品类型以及仅描述该商品的特殊属性。这时联合体比结构体更加节省空间。因此使用哪一种自定义类型取决于描述的对象。


二、枚举类型

2.1 枚举类型的声明

枚举类型(Enum)是一种用于定义命名整数常量的数据类型。 允许程序员为一组相关的整数值分配有意义的名称,以提高代码的可读性和可维护性。

enum 枚举名称 {
    枚举值1,
    枚举值2,
    // 可以有更多的枚举值
};

举例,列举颜色:

#include
enum Color{//颜⾊
	RED,
	GREEN,
	BLUE
};
int main() {
	printf("%d %d %d",RED,GREEN,BLUE);
	return 0;
}

运行结果:
【C语言】自定义类型:联合和枚举_第6张图片
枚举常量的从0开始,当然我们可以自己赋值:

#include

enum Color{//颜⾊
	RED,
	GREEN=5,
	BLUE
};
int main() {
	printf("%d %d %d",RED,GREEN,BLUE);
	return 0;
}

运行结果:
【C语言】自定义类型:联合和枚举_第7张图片

2.2 枚举的优点

枚举的优点:

  1. 增加代码的可读性和可维护性
  2. 和#define定义的标识符⽐较枚举有类型检查,更加严谨。
  3. 便于调试,预处理阶段会删除 #define 定义的符号
  4. 使用⽅便,⼀次可以定义多个常量
  5. 枚举常量是遵循作⽤域规则的,枚举声明在函数内,只能在函数内使用

2.3 枚举的应用场景

  1. 定义枚举类型
enum Weekday {
    MONDAY,
    TUESDAY,
    WEDNESDAY,
    THURSDAY,
    FRIDAY,
    SATURDAY,
    SUNDAY
};
  1. 声明和使用枚举变量
enum Weekday today = TUESDAY;
  1. 使用枚举值
if (today == MONDAY) {
    printf("今天是星期一\n");
} else if (today == TUESDAY) {
    printf("今天是星期二\n");
}

  1. 开关语句中的枚举
switch (today) {
    case MONDAY:
        printf("今天是星期一\n");
        break;
    case TUESDAY:
        printf("今天是星期二\n");
        break;
    // 其他星期几的情况
    default:
        printf("今天不是星期一或星期二\n");
        break;
}

枚举的使用与#define定义常量类似,但枚举和#define定义的标识符⽐较枚举有类型检查,更加严谨。


【C语言】自定义类型:联合和枚举_第8张图片
如果你喜欢这篇文章,点赞+评论+关注⭐️哦!
欢迎大家提出疑问,以及不同的见解。

你可能感兴趣的:(c语言,开发语言,学习)