C语言关于自定义数据类型之枚举和联合体详解

目录
  • 前言
    • 枚举
      • 枚举类型的定义
      • 枚举类型的优点
      • 枚举类型的使用
      • 枚举中需要注意的点
    • 联合体
      • 联合体类型的定义
      • 联合体的特点
      • 联合体的使用
      • 联合体存在内存对齐
  • 结语

前言

在C语言的自定义数据类型中,除了我们最为常用的结构体之外,还有两个比较少用的自定义数据类型,分别为枚举和联合体(也可以称为共用体)。

今天,我们一起看学习一下相关的知识吧!

枚举

什么是枚举?

顾名思义,就是一一列举,把所有的情况,所有的取值,一一列举出来。

在我们生活中,有不少的东西是可以全部列举出来的。

如一个星期有七天,一年有十二个月,性别有男和女,评价有优秀、良好、及格和不及格等等。

当某些数据的值只有固定的几种可能取值的时候,我们就可以使用枚举类型。

枚举类型的定义

enum 枚举类型名 { 枚举值1 ,枚举值2,… ,枚举值n };

枚举类型的定义和结构体类似,先使用enum这个关键字,后面加上枚举类型的名字,括号内是枚举的值,最后别忘记分号。

还有,最后的一个枚举值后面不需要逗号!

一般定义枚举类型的方法如下:

注意:这是定义枚举类型,而不是定义枚举变量!

例如如下:

enum Day//星期
{
	Mon,
	Tues,
	Wed,
	Thur,
	Fri,
	Sat,
	Sun
};

enum Sex//性别
{
	MALE,
	FEMALE,
	SECRET
};

enum Color//颜色
{
	RED,
	GREEN,
	BLUE
};

此外,还有其他的一些定义的方法。

枚举类型的优点

那么我们来思考一个问题,为什么需要枚举呢?

我们其实可以通过#define的方式来定义常量,那么我们还需要定义枚举吗?

其实是需要的。

在有些情况下,枚举可以让我们的代码更加清晰明了。

比如,我们在需要打印菜单的时候,就需要有不同的选项,那么每一个选项就对应一个值,那么我们可以使用枚举让数值与对应的含义对上号,那么这就可以让我们在实现每一个具体的细节的时候,知道这一种case情况对应的具体含义。

此外,还有别的优点:

  • 防止了命名污染(封装)
  • 便于调试
  • 使用方便,一次可以定义多个常量

枚举类型的使用

通过枚举类型,我们可以定义枚举变量

enum Color//颜色
{
	RED,
	GREEN,
	BLUE
};

//使用方法和其他类型一直,就像int a;一样
enum Color clr;

//使用枚举值来给枚举类型赋值
clr = RED;

//注意,一般我们给枚举赋值的时候,都用枚举值,而不用其他的值,否则就没有什么意义了

我们一般使用结构体的时候,都像上面的栗子一样。

先创建好枚举的模板,燃用这个模板来创建变量。

此外,还有其他的方法:

创建模板的同时定义枚举变量

enum Color//颜色
{
	RED,
	GREEN,
	BLUE
}clr1,clr2;//在最后这里,我们定义了两个枚举变量

省略枚举类型名字,匿名创建枚举变量

enum
{
	RED,
	GREEN,
	BLUE
}clr1,clr2;//这里定义了两个枚举变量

上面的两个变量依旧可以使用,只是,我们没有写出该枚举类型的名字,就只能这样来定义变量,以后不能在利用这个模板来创建变量了

使用typedef来给枚举类型重命名

typedef enum Color//颜色
{
	RED,
	GREEN,
	BLUE
}cr;//注意,这里的cr是新的枚举类型名字,不是定义的枚举变量

//还可以匿名重命名

typedef enum
{
	RED,
	GREEN,
	BLUE
}cr;

枚举中需要注意的点

  • 枚举值只能是整型的数据,如字符、整数等,不能是浮点型
  • 枚举类型变量赋值的时候,一般用枚举值来赋值,不适用其他的数值来赋值
  • 枚举值本身是一个常量,我们可以对枚举变量的值进行修改,但不能对枚举值进行修改
  • 枚举值被处理的时候,会被看成整数数值,因此枚举变量可以算术运算、关系运算等

联合体

联合体类型的定义

union 联合体类型名 { 数据类型 成员名1 , 数据类型 成员名 2 , … , 数据类型 成员名n;};

联合体也叫共用体,这个也是一种特殊的数据类型。

这种类型定义的变量也包含一系列的成员,特征是这些成员公用同一块空间。

栗子如下:

union Un
{
	char c;
	int i;
};

联合体的特点

联合体变量的成员是使用共同的一块空间的。

联合体的大小,至少是成员中最大成员的大小。
(这里的至少我们后面再说)

#include<stdio.h>

union Un
{
	int i;
	char c;
};
union Un un;

int main() {

	// 下面输出的结果是一样的吗?
	printf("%p\n", &un);
	printf("%p\n", &(un.i));
	printf("%p\n", &(un.c));

	return 0;
}

运行上面的代码,我们会发现三个地址都相同

成员变量i是第一个成员,该地址和联合体的地址相同我们可以理解,c作为第二个成员变量,其地址也是和第一个成员变量的地址相同,那么这就说明,它们确实使用的是同一块空间

联合体的使用

联合体类型定义变量的方法,和结构体、枚举类似,都有多种方法

先创建模板,在定义变量

union Un
{
	int i;
	char c;
};
union Un un;

创建模板的同时定义变量

union Un
{
	int i;
	char c;
}un;//此处的un是一个联合体变量

匿名定义联合体变量

union
{
	int i;
	char c;
}un;//此处的un是一个联合体变量

同样的,由于联合体类型名的省略,我们只可以这样来定义变量,后面就再也不能使用该模板来定义变量了

typedef重命名联合体类型名

typedef union Un
{
	int i;
	char c;
}un;

typedef union
{
	int i;
	char c;
}un;

联合体存在内存对齐

上面说到,联合体的大小,至少是最大成员变量的大小。为什么是至少呢?

我们先来看下面的栗子:

union Un
{
	char arr[6];
	short s;
};

union Un u;

int main() {

	// 下面输出的结果是一样的吗?
	printf("%u", sizeof(union Un));

	return 0;
}

上面的代码输出的结果为6

如果我们把字符数组的大小改成5,会发现大小还是6

这是因为,联合体中也存在着对齐

上面的栗子中,会认为字符数组的默认对齐数为1,而short的默认对其数位2,但是成员变量的大小会根据数组的大小来计算,而不是根据数组的元素类型。假如你是元素个数为6的字符数组,那么大小就是6,元素个数为5的字符数组,大小就是5,而int、short等数据类型就按照默认的大小来计算。

首先需要联合体的大小至少是最大成员变量的大小。

然后要求大小应该为各个成员变量中,最大对齐数的倍数,如果不是倍数,那么对齐到整数倍处。

这就能说明,为什么上面的代码把字符数组的大小改为5个元素的时候,联合体的大小仍然为6.

结语

今天的分享到这里就结束啦!

由于本人能力有限,难免会有出错的地方,还希望各位能够指出!

希望各位能给我点个赞、点个收藏哦~

谢谢支持!

到此这篇关于C语言关于自定义数据类型之枚举和联合体详解的文章就介绍到这了,更多相关C语言 自定义数据类型内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C语言自定义类型详解(结构体、枚举、联合体和位段)

    目录 前言 一.结构体 1.结构体类型的声明 2.结构体的自引用 3.结构体变量的定义和初始化 4.结构体内存对齐 5.结构体传参 二.位段 1.位段的定义 2.位段的内存分配 3.位段的应用 三.枚举 1.枚举类型的定义 2.枚举的优点 3.枚举的使用 四.联合体(共用体) 1.联合体的定义 2.联合体的特点 3.联合体的大小计算 总结 前言 一.结构体 1.结构体类型的声明 当我们想要描述一个复杂变量--学生,可以这样声明. ✒️代码展示: struct Stu { char name[20

  • C语言中枚举与联合体的使用方法(enum union)

    目录 enum的定义 enum对比#define宏常量的好处 union的定义 联合体大小的计算 联合体配合算大小端的问题 总结 enum的定义 枚举顾名思义就是一一列举,把可能的取值一一列举. 枚举的使用方式 //定义一个枚举Color的类型 enum Color // enum Color 是一个类型 { RED, //逗号结尾 GREEN, BLUE // 最后一个成员没有逗号没有分号 }; int main() { printf("%d",RED);//0 printf(&qu

  • c语言枚举类型enum的用法及应用实例

    目录 前言 一.枚举的概念 二.枚举的几种用法 1.直接定义枚举值,然后给普通变量赋值. 2.定义带名称的枚举 三.定义枚举别名 四.枚举有什么用,用在哪里? 最后总结: 前言 今天跟大家讲一下我在产品开发时,用枚举(enum)的一些骚操作. 我跟你保证,今天的内容绝对是你在书本和视频学不到的. 为什么要讲枚举呢? 因为我发现它是一个容易被遗忘,同时又非常重要的关键词,大家如果看那些大佬写的程序,真的会发现有非常非常多enum的应用. 让我惊奇的是市面上的一些C语言书籍以及视频课程并没有重视去讲

  • C语言结构体,枚举,联合体详解

    目录 1.什么是结构体.枚举.联合体 2.定义结构体 2.1 包含结构体成员变量.variable 2.2 tag.结构体成员变量 2.3 用结构体声名变量 2.4 用typedef 创建新类型 2.5 两个结构体相互包含 2.6 结构体变量初始化 2.7 结构体指针 3.枚举 3.1 定义方式 3.2 为什么用枚举 3.3 枚举变量的定义 3.4 实例 3.5 枚举实际用途 4.联合体 4.1 与结构体区别 4.2 定义 总结 1.什么是结构体.枚举.联合体 结构体(struct)是由一系列具

  • C语言关于自定义数据类型之枚举和联合体详解

    目录 前言 枚举 枚举类型的定义 枚举类型的优点 枚举类型的使用 枚举中需要注意的点 联合体 联合体类型的定义 联合体的特点 联合体的使用 联合体存在内存对齐 结语 前言 在C语言的自定义数据类型中,除了我们最为常用的结构体之外,还有两个比较少用的自定义数据类型,分别为枚举和联合体(也可以称为共用体). 今天,我们一起看学习一下相关的知识吧! 枚举 什么是枚举? 顾名思义,就是一一列举,把所有的情况,所有的取值,一一列举出来. 在我们生活中,有不少的东西是可以全部列举出来的. 如一个星期有七天,

  • C语言自定义数据类型的结构体、枚举和联合详解

    结构体基础知识 首先结构体的出现是因为我们使用C语言的基本类型无法满足我们的需求,比如我们要描述一本书,就需要书名,作者,价格,出版社等等一系列的属性,无疑C语言的基本数据类型无法解决,所以就出现了最重要的自定义数据类型,结构体. 首先我们创建一个书的结构体类型来认识一下 struct Book { char name[20]; char author[20]; int price; }; 首先是struct是结构体关键字,用来告诉编译器你这里声明的是一个结构体类型而不是其他的东西,然后是Boo

  • C语言中的自定义类型之结构体与枚举和联合详解

    目录 1.结构体 1.1结构的基础知识 1.2结构的声明 1.3特殊的声明 1.4结构的自引用 1.5结构体变量的定义和初始化 1.6结构体内存对齐 1.7修改默认对齐数 1.8结构体传参 2.位段 2.1什么是位段 2.2位段的内存分配 2.3位段的跨平台问题 2.4位段的应用 3.枚举 3.1枚举类型的定义 3.2枚举的优点 3.3枚举的使用 4.联合 4.1联合类型的定义 4.2联合的特点 4.3联合大小的计算 1.结构体 1.1结构的基础知识 结构是一些值的集合,这些值称为成员变量.结构

  • C语言实现进制转换函数的实例详解

    C语言实现进制转换函数的实例详解 前言: 写一个二进制,八进制,十六进制转换为十进制的函数 要求: 函数有两个参数,参数(1)是要转换为十进制的进制数,参数(2)是标示参数(1)是什么进制(2,8,16标示二进制,八进制,十六进制). 要有报错信息,比如参数是1012,但参数(2)是2,显然是进制数表示有错误. 系统表 pg_proc 存储关于函数的信息 内部函数在编译之前需要先定义在 pg_proc.h 中,src/include/catalog/pg_proc.h CATALOG(pg_pr

  • Go语言学习之结构体和方法使用详解

    目录 1. 结构体别名定义 2. 工厂模式 3. Tag 原信息 4. 匿名字段 5. 方法 1. 结构体别名定义 变量别名定义 package main import "fmt" type integer int func main() { //类型别名定义 var i integer = 1000 fmt.Printf("值: %d, 类型: %T\n", i, i) var j int = 100 j = int(i) //j和i不属于同一类型,需要转换 fm

  • C语言程序中结构体的内存对齐详解

    目录 一.为什么存在内存对齐 二.结构体的内存对齐四规则 三.举例 一.为什么存在内存对齐 1.平台原因(移植原因): 不是所有的硬件平台都能访问任意地址上的任意数据的:某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常. 2. 性能原因: 数据结构(尤其是栈)应该尽可能地在自然边界上对齐. 原因在于,为了访问未对齐的内存,处理器需要作两次内存访问:而对齐的内存访问仅需要一次访问. 总的来说结构体的内存对齐是拿空间来换取时间的做法. 二.结构体的内存对齐四规则 默认情况:默认的对

  • Java语言面向对象编程思想之类与对象实例详解

    在初学者学Java的时候,面向对象很难让人搞懂,那么今天小编就来为大家把这个思想来为大家用极为简单的方法理解吧. 首先我们来简单的阐述面向对象的思想. 面向对象: 官方的语言很抽象,我们把官方的解释和定义抛开.想想,自己有什么,对!!我们自己有手脚眼口鼻等一系列的器官.来把自己所具有的器官就可以看作我们的属性,自己是不是可以喜怒哀乐和嬉笑怒骂,这些是不是我们的行为,那么自己的具有的属性加自己有的行为就称为一个对象. 注意!!我们自己,一个个体是一个对象,因为,你是你,我是我,我们虽然有相同的,但

  • python语言time库和datetime库基本使用详解

    今天是边复习边创作博客的第三天,我今年大二,我们专业开的有这门课程,因为喜欢所以更加认真学习,本以为没人看呢,看了后台浏览量让我更加认真创作,这篇博客花了2个半小时的时间,结合自己所学,所思,所想写作,目的是为了方便喜欢Python的小白学习,也是一种自我鞭策吧! python语言使用内置time库和datetime库来处理日期时间 相关术语的解释 UTC time Coordinated Universal Time,世界协调时,又称 格林尼治天文时间.世界标准时间.与UTC time对应的是

  • C语言入门篇--注释,关键字typedef及转义字符详解

    目录 注释 1.注释意义 2.两种注释风格 2.1 C语言注释风格 2.2 C++注释风格 关键字typedef 1.注意 2.用法 语法结构 转义字符 1.转义字符及其含义 2.字面 转 特殊 3.特殊 转 字面 注释 1.注释意义 (1)代码中有不需要的代码可以直接删除,也可以注释掉. (2)有些代码比较难懂可以注释一下. 2.两种注释风格 2.1 C语言注释风格 /*xxxxxx*/ 一次可以注释一行或多行,但不能嵌套注释. eg: #include <stdio.h> int main

  • SpringBoot在RequestBody中使用枚举参数案例详解

    前文说到 优雅的使用枚举参数 和 实现原理,本文继续说一下如何在 RequestBody 中优雅使用枚举. 本文先上实战,说一下如何实现.在 优雅的使用枚举参数 代码的基础上,我们继续实现. 确认需求 需求与前文类似,只不过这里需要是在 RequestBody 中使用.与前文不同的是,这种请求是通过 Http Body 的方式传输到后端,通常是 json 或 xml 格式,Spring 默认借助 Jackson 反序列化为对象. 同样的,我们需要在枚举中定义 int 类型的 id.String

随机推荐