
🌈这里是say-fall分享,感兴趣欢迎三连与评论区留言
🔥专栏:《C语言入门知识点》、《C语言底层》、《精通C语言》、《C语言编程实战》
💪格言:做好你自己,你才能吸引更多人,并与他们共赢,这才是你最好的成长方式。
前言:
在我们学习完自定义类型:结构体以后,我们不禁会好奇,有没有其他的自定义类型呢?他们又是用来干啥的呢?今天我们就来了解一下另外两种自定义类型:枚举和联合体,感兴趣的小伙伴快记好笔记~
文章目录
- 前言:
- 正文:
-
- [1. 联合体](#1. 联合体)
-
- [1.1 联合体是什么?](#1.1 联合体是什么?)
- [1.2 联合体的声明与特点](#1.2 联合体的声明与特点)
- [1.3 联合体大小的计算](#1.3 联合体大小的计算)
- [1.4 联合体的实际用处](#1.4 联合体的实际用处)
- [1.5 联合的⼀个练习](#1.5 联合的⼀个练习)
- [2. 枚举](#2. 枚举)
-
- [2.1 枚举的声明](#2.1 枚举的声明)
- [2.2 枚举的意义](#2.2 枚举的意义)
- [2.3 枚举常量和枚举变量](#2.3 枚举常量和枚举变量)
正文:
1. 联合体
1.1 联合体是什么?
既然我们之前学过了结构体,那对于联合体是什么这个问题就很好解释了,先来看一段代码:
c
//1.
union test1
{
char c;
int i;
};
c
//2.
struct test1
{
char c;
int i;
};
我们发现上面第一段代码就是将结构体的关键字换为了
union
,这个union
是什么呢?其实他就是联合体的关键字,而第一段代码也就是整个联合体的声明
1.2 联合体的声明与特点
联合体的声明其实就是上面的样子,标准形式也与结构体的声明基本一致,那么他们究竟不一样在那里呢?
- 联合体的声明:
像结构体⼀样,联合体也是由⼀个或者多个成员构成,这些成员可以不同的类型。
但是编译器只为最⼤的成员分配⾜够的内存空间。联合体的特点是所有成员共⽤同⼀块内存空间。所以联合体也叫:共⽤体
。
给联合体其中⼀个成员赋值,其他成员的值也跟着变化。
那他的内存占用是什么样子的呢?
我们依旧是用代码来说明:
c
#include <stdio.h>
union test1
{
char c;
int i;
};
struct test2
{
char c;
int i;
};
int main()
{
printf("%zd\n", sizeof(union test1));
printf("%zd\n", sizeof(struct test2));
return 0;
}
运行结果:
c
4
8
可以看到内存占用的字节数
4
和8
,下面我们来解释一下:
c
#include <stdio.h>
union test1
{
char c;
int i;
};
struct test2
{
char c;
int i;
};
int main()
{
printf("%zd\n", sizeof(union test1));
printf("%zd\n", sizeof(struct test2));
union test1 un1 = { 0 };
un1.i = 0x44332211;
un1.c = 5;
return 0;
}
调试一下:
可以看到确实很符合联合体的特点:"所用成员共用一块内存空间 ",这也就是这个联合体只占四个字节看空间大小的原因了
那是不是联合体的内存空间就占最大的一个成员变量空间大小就行了呢?
1.3 联合体大小的计算
- 规则
- 联合的⼤⼩⾄少是最⼤成员的⼤⼩。
- 当最⼤成员⼤⼩不是最⼤对⻬数的整数倍的时候,就要对⻬到最⼤对⻬数的整数倍。
也就是说,联合体也是有一种内存对齐的
c
union test3
{
char ch[5];
int i;
};
int main()
{
printf("zd\n", sizeof(union test3));
return 0;
}
运行结果:
c
12
这段代码出现12个字节的原因就是
char ch[5]
占了5个字节,int i
本来要占4个字节变为9个,但是由于联合体内存只能是4的整数倍,就导致了int i
向后偏移了3个字节,总内存大小就变成了12个字节
1.4 联合体的实际用处
使⽤联合体是可以节省空间的,举例:
⽐如,我们要搞⼀个活动,要上线⼀个礼品兑换单,礼品兑换单中有三种商品:图书、杯⼦、衬衫 。每⼀种商品都有:
库存量、价格、商品类型
和商品类型相关的其他信息
。图书:书名、作者、⻚数
杯⼦:设计
衬衫:设计、可选颜⾊、可选尺⼨
在我们不用联合体的情况下直接使用结构体无非就是把这些都放到一个结构体里嘛
c
struct sell
{
int Inventory_quantity;//库存
float price;//价格
char product_type[30];//商品类型
char Title[30];//书名
char Author[30];//作者
int Number_of_Pages;//页数
char design[30];//设计
char colar[30];//可选颜色
int size;//可选尺寸
};
但是我们会发现其中有一些重复的成员变量:库存量、价格和商品类型
这样子的话其他东西实际上是" 选择使用 "的,我们就可以把他们封装在联合体里面
c
struct sell
{
int Inventory_quantity;//库存
float price;//价格
char product_type[30];//商品类型
union
{
struct
{
char Title[30];//书名
char Author[30];//作者
int Number_of_Pages;//页数
}book;
struct
{
char design[30];//设计
}mug;
struct
{
char design[30];//设计
char colar[30];//可选颜色
int size;//可选尺寸
}shirt;
};
}item;
通过这种封装的方式,就能节省大量的空间,因为空间是按照最大的那个结构体空间大小来开辟的
1.5 联合的⼀个练习
写⼀个程序,判断当前机器是⼤端?还是⼩端?
记得之前我们是怎么做的吗?是通过读取第一个地址上储存的二进制数字来判断的
c
int main()
{
int a = 1;
if (*((char*)&a) == 1)
{
printf("小端");
}
else
{
printf("大端");
}
return 0;
}
而我们有了联合体之后就能简化他
c
int check_sys()
{
union
{
int i;
char c;
}un;
un.i = 1;
return un.c;//返回1是⼩端,返回0是⼤端
}
以上就是联合体的所有内容了
2. 枚举
2.1 枚举的声明
枚举,在中文里面就是一一列举的意思,像是一只羊、两只羊地数羊
下面我们看一下枚举的声明
c
// 定义枚举类型
enum 枚举名 {
常量1, // 默认值为0
常量2, // 默认值为1(前一个常量+1)
常量3 = 5, // 手动指定值为5
常量4 // 自动为6(前一个常量+1)
};
就是像这样,他会把列出来的变量赋值数字,默认是从1开始+1 ,如果人为赋值就会变为改变值然后继续+1
2.2 枚举的意义
我们为什么要把这些变量名通过枚举的方式赋值
如果要给常量赋值明明可以用 #define
的方式
下面我们来看一下枚举的优点
- 枚举的优点:
- 增加代码的可读性和可维护性
- 和
#define
定义的标识符⽐较枚举有类型检查,更加严谨。 - 便于调试,预处理阶段会删除
#define
定义的符号 - 使⽤⽅便,⼀次可以定义多个常量
- 枚举常量是遵循作⽤域规则的,枚举声明在函数内,只能在函数内使⽤
2.3 枚举常量和枚举变量
-
枚举常量:
枚举常量是枚举类型定义时声明的***固定值***,是枚举类型的 "成员",本质是被命名的整数常量。
-
枚举变量:
枚举变量是`声明为枚举类型的变量`,它可以存储枚举常量中的某一个值。
举例:
c
enum color//里面定义的是枚举常量
{
red,
green,
blue,
yellow
};
enum color lor = green;//这个是枚举变量
他们的关键区别在于常量是固定的,用来增加代码可读性的;而变量是可以赋值的,枚举变量本质上存储的是枚举常量对应的整数,但编译器会检查赋值是否属于该枚举类型(部分语言如 C++ 更严格)。
那是否可以拿整数给枚举变量赋值呢?在C语⾔中是可以的,但是在C++是不⾏的,C++的类型检查⽐较严格,同上。
c
enum color
{
red,
green,
blue,
yellow
};
enum color lor = 2;//C语言行,c++不行
以上就是枚举的所有要点了
- 本节完...