【C语言】联合体和枚举

本文详细介绍了C语言中的联合体和枚举类型,包括联合体的声明、特点(共用内存空间和覆盖现象)、大小计算,以及枚举类型(声明、优点和使用方法)。同时,对比了结构体与联合体的差异,展示了C语言中这两种自定义类型的特点和应用场景。
摘要由CSDN通过智能技术生成

前言

这篇博客就把剩下的两个自定义类型联合体和枚举好好总结一下,让我们好好看看联合体和枚举到底是什么

个人主页:小张同学zkf

若有问题 评论区见

感兴趣就关注一下吧

目录

 1. 联合体

1.1 联合体类型的声明

 1.2 联合体的特点

 1.3 相同成员的结构体和联合体对比

 1.4 联合体大小的计算

2. 枚举类型

2.1 枚举类型的声明

2.2 枚举类型的优点

 2.3 枚举类型的使用

 


 1. 联合体

1.1 联合体类型的声明

像结构体一样,联合体也是由一个或者多个成员构成,这些成员可以不同的类型。
但是编译器只为最大的成员分配足够的内存空间。联合体的特点是所有成员共用同一块内存空间。所以联合体也叫:共用体
给联合体其中一个成员赋值,其他成员的值也跟着变化。
# include <stdio.h>
// 联合类型的声明
union Un
{
char c;
int i;
};
int main ()
{
// 联合变量的定义
union Un un = { 0 };
// 计算连个变量的⼤⼩
printf ( "%d\n" , sizeof (un));
return 0 ;
}

输出结果:4

由图可见他们俩共处一个空间,所以字节长度为最大的类型int

 1.2 联合体的特点

联合的成员是共用同一块内存空间的,这样一个联合变量的大小,至少是最大成员的大(因为联合
至少得有能力保存最大的那个成员)。
# 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

由图可知是将最低位由于联合体的特点,覆盖成c的55。

那我们想一下,既然c和i共处一室,它们的地址会一样吗?

我们试一下

# include <stdio.h>
// 联合类型的声明
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 ;
}

输出结果:

001 AF85C
001 AF85C
001 AF85C

可见输出结果一样,这也就说明联合体地址和里面每个成员名的地址是一样的

 1.3 相同成员的结构体和联合体对比

我们再对比一下相同成员的结构体和联合体的内存布局情况。
struct S                                   
{
char c;
int i;
};
struct S s = { 0 }; 
 
union Un
{
char c;
int i;
};
union Un un = { 0 };

联合体相较于结构体可以节省空间,但是它会出现成员与成员覆盖的情况 

 1.4 联合体大小的计算

 我们了解了联合体在内存中的布局,那联合体的字节大小到底怎么计算那

我们首先要知道:

联合的大小至少是最大成员的大小
当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍。

我们来看一个代码加深理解
# 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 ;
}

我们先分析un1,根据前面博客分析的结构体而言,char的最大对齐数是1,int的最大对齐数为4,所以这个联合体的最大对齐数为4,联合体至少也是最大成员的空间,成员中最大的空间是char c[5],为5,5不是4的倍数,所以对齐到8的位置,就是8;再看un2,un2至少为14个字节吧,short和int的对齐数分别为2和4,所以最大对齐数为4,14不是4的倍数,所以要对齐到16的位置,大小为16。

我们认识了联合体,那我们是不是又有一种巧妙的方式判断大小端了

int check_sys ()
{
union
{
int i;
char c;
}un;
un.i = 1 ;
return un.c; // 返回 1 是⼩端,返回 0 是⼤端
}

既然char成员占据低地址处的位置,那此时i为1,返回c,正好可以直接判断这个位置上的数字。 


2. 枚举类型

枚举是 C 语言中的一种基本数据类型,用于定义一组具有离散值的常量

2.1 枚举类型的声明

枚举顾名思义就是一 一列举。
把可能的取值一 一列举。
比如我们现实生活中:
一周的星期一到星期日是有限的7天,可以一 一列举
性别有:男、女、保密,也可以⼀⼀列举
月份有12个月,也可以⼀⼀列举
三原色,也是可以一 一列举

 这些数据的表示就可以使用枚举了。

enum Day // 星期
{
Mon,
Tues,
Wed,
Thur,
Fri,
Sat,
Sun
};
enum Sex // 性别
{
MALE,
FEMALE,
SECRET
}
enum Color // 颜⾊
{
RED,
GREEN,
BLUE
};
以上定义的 enum Day enum Sex enum Color 都是 枚举类型
{}中的内容是枚举类型的可能取值,也叫 枚举常量

这些可能取值都是有值的,默认从0开始,依次递增1,当然在声明枚举类型的时候也可以赋初值。

比如:

enum Color // 颜⾊
{
RED= 2 ,
GREEN= 4 ,
BLUE= 8
};

若不赋初值

enum Color // 颜⾊
{
RED ,//0
GREEN ,//1
BLUE//2
};

那里面的常量值就默认从0开始依次加一

若中间赋初值

enum Color // 颜⾊
{
RED ,//0
GREEN ,//1
BLUE=8,//8
YELLOW//9
};

可见刚开始不赋初值的时候,依然从零开始依次加一,从哪开始赋初值,就从这个初值的基础上依次加一。

2.2 枚举类型的优点

这时肯定有人会想定义常量的话,那我们可以用#define宏定义呀,为什么会有枚举这东西那

相比#define枚举可以调试,而#define在调试时会直接在预处理阶段替换。

我们来看一下枚举的优点就知道了

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

 2.3 枚举类型的使用

enum Color // 颜⾊
  {
 RED= 1 ,
 GREEN= 2 ,
 BLUE= 4
  };
  enum Color clr = GREEN;
那是否可以拿整数给枚举变量赋值呢?在C语言中是可以的,但是在C++是不行的,C++的类型检查比较严格。


结束语

枚举和联合体总结完了,这两个和上一篇的结构体都可以用typedef关键字重命名,好了全部自定义类型总结完了

OK,感谢观看

 

评论 52
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值