当前位置: 首页 > news >正文

赶紧进来看看---详解C/C++中的自定义类型:枚举和联合体

本文介绍了C/C++中两个自定义类型:枚举–enum和联合体–union
主要涉及两种类型的声明,定义,使用.特点,类型大小的计算…
继上篇自定义类型:结构体 --struct

C/C++自定义类型:枚举和联合体

  • 一.枚举 --enum
    • 1.枚举类型的定义
    • 2.枚举常量取值规则
    • 3.枚举类型的使用
    • 4.枚举类型的优点
  • 二.联合体(共用体) --union
    • 1.联合体类型的声明
    • 2.联合体类型的特点
    • 3.联合体大小的计算
  • 三.枚举和联合体类型总结

一.枚举 --enum

枚举顾名思义就是:一一列举.
它是C/C++中一种自定义类型,当我们想表达有限个数据时,可以使用到枚举类型,
比如要表达性别可以是:男,女,保密
表达一周有多少天:星期一到星期天
表达特定的颜色–三原色:红绿蓝 等等
这些有限个的数据都可以一一列举.就可以使用枚举将数据作为枚举常量来表示, 当我们用数字来表示一些有意义的值时,难免会出现混淆,忘记的情况,而用枚举常量来代替这些要表达的数字,二者含义一样,但是枚举 而可以使数据更简洁,可读性高等…

1.枚举类型的定义

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 都是枚举类型。enum为枚举类型 后面的Day为枚举标签(枚举名)类似于结构体标签.用来标识每个不同枚举,
{}中的内容是枚举类型的可能取值,也叫 枚举常量(一般是大写的标识符)
注意:枚举常量间用 ,逗号隔开,最后一个不用逗号, 最后要加上分号;

2.枚举常量取值规则

定义枚举类型后,它内部枚举常量都是些大写标识符,每个标识符都有自己的常量值,也可以在定义枚举常量时初始化一个常量值
这些可能取值都是有值的,如果没有初始化常量值默认第一个是从0开始,后面的枚举常量依次递增1,

#include<stdio.h>
enum color
{
	RED,
	GREEN,
	BLUE
};
int main()
{
	printf("%d %d %d", RED, GREEN, BLUE);//输出结果是什么
	return 0;
}

根据上面规则得出 不对其初始化时第一个开始默认是0后面的枚举常量依次递增1 ,结果为0 1 2

在这里插入图片描述

#include<stdio.h>
enum color
{
	RED,
	GREEN=66,
	BLUE
};
int main()
{
	printf("%d %d %d", RED, GREEN, BLUE); //运行结果是什么
	return 0;
}

根据规则第一个没初始化默认为0,而第二个枚举常量初始化为了66,第三个未初始化根据第二个初始化为66 后递增规则 第三个表达的常量值是67 运行结果为0 66 67

在这里插入图片描述

3.枚举类型的使用

在声明枚举类型后,可以用枚举类型定义变量,其变量取值只能是枚举常量里的其中一个,用于枚举常量赋于变量表示特定标识性的含义

#include<stdio.h>
enum color
{
	RED,
	GREEN=66,
	BLUE
};
int main()
{
	enum color num = GREEN;
    printf("%d\n",sizeof(enum color));
	printf("%d\n",num);
	num = RED;
	printf("%d\n", num);
	num = BLUE;
	printf("%d", num);
	
	return 0;      //输出结果是什么?
}

enum color枚举类型里面的成员是枚举常量即可能取值,用enum color 枚举类型创建变量num只能赋值枚举类型里的任意一个枚举常量,而每个枚举常量都是整形,根据特性,其sizeof求枚举类型的类型大小是一个整形大小是4个字节.
而num赋值上特定的枚举常量后,其表达的意义也就是对应枚举常量表示的整形值
最后输出 4 66 0 67

枚举常量即用一些特殊意义的标识符其自身还是整数属性,但比整数可读性更高,这类似于#define宏定义的符号常量,但是枚举有比#define突出的优点…

4.枚举类型的优点

我们可以使用 #define 定义常量,为什么非要使用枚举? 枚举的优点

  1. 增加代码的可读性和可维护性

枚举常量更具有标识性,自身含义和数字相同,但是是以标识符等形式出现比直接用数字可读性和可维护性更高

  1. 和#define定义的标识符比较枚举有类型检查,更加严谨。

enum类型有自身声明是对应的枚举标签,比#define更严谨,有类型可检查,而#define没有分类

  1. 防止了命名污染(封装)

用枚举常量赋予了该标识符特殊的意义以供使用

  1. 便于调试

枚举常量比数字可读性更高,比如一些用数字作为选项的参数可以用枚举常量替代,调试除错的效率更高

  1. 使用方便,一次可以定义多个常量

#define宏定义的标识符常量只能写一个#define定义一个符号常量,而enum 枚举类型声明后可以在{}里添加多个常量.比#define更方便

二.联合体(共用体) --union

联合体又称结构体,是一种自定义类型,这种类型定义的变量也包含一系列的成员
特点是该类型里的成员变量占用同一块内存空间,
当需要单独描述某个对象时如:在学校上学时是一个学生,毕业后在这个学校是一个教授,通过改变联合体类型里的一个成员变量就能影响整个类型的成员变量值,比使用其他类型描述单个对象更便捷,更节省空间

1.联合体类型的声明

//联合类型的声明
union Un
{
char c;
int i;
};
//联合变量的定义
union Un un;

联合体类型关键字为union 右边的Un是联合体名即标签,用来区分不同的联合体类型
{}里面是所有联合体成员变量,它们共用一块内存空间,最后要加上;

2.联合体类型的特点

联合的成员是共用同一块内存空间的,这样一个联合变量的大小,至少是最大成员的大小(因为联合至少得有能力保存最大的那个成员.

#include<stdio.h>
union Un
{
	int i;
	char c;
};
union Un un;
// 下面输出的结果是一样的吗?
int main()
{
	printf("%p\n", &(un.i));
	printf("%p\n", &(un.c));
	un.i = 0x11223344;
	
	printf("%x\n", un.i);
	un.c = 0x55;
	printf("%x\n", un.i);
	return 0;
}

因为联合体内的成员变量共用一块内存空间, int i四个字节空间,char c 一个字节空间 ,根据规则它们共开辟四个字节空间,而char c占起始地址开始的一个字节空间即低地址空间.

在这里插入图片描述

而&(un.i)求整形变量i的空间得到起始地址–第一个内存单元地址
&(un.c)求字符变量c的空间因为c是和i共用空间用的起始地址上内存单元的空间也就是i第一个内存单元地址,所有&(un.i)和&(un.c)地址表示方式是一样的,

un.i=0x11223344表示将成员变量i里赋值一个十六进制形式的整数,而当前编译器是小端形式 内存里分布是 44 33 22 11
最低地址处的内存单元里的数据是44,此时输出un.i按小端形式取出输出结果是11223344
然后un.c=0x55表示将联合体里c成员变量赋值为0x55
而c占的空间就是i里四个内存单元地址最小的内存单元,即将44改为了55,
此时联合体里的所有成员内存分布为55 33 22 11
按十六进制形式输出 结果为11223355

在这里插入图片描述
在这里插入图片描述

3.联合体大小的计算

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

对齐数概念在这篇介绍结构体类型博客中介绍到->对齐数

#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;
}

union Un1中最大成员大小是char c[5]共五个内存单元 ,联合体成员总大小最小要是5
而char c[5]对齐数是char类型大小和默认对齐数8取较小的为1字节,而int i对齐数则是4字节, 5不是4的倍数要对齐到4的倍数最后总大小为8

union Un2中最大成员大小是short c[7]共2*7为14个内存单元,联合体成员总大小最小要是14,而short c[7]每个元素是short类型 对齐数是short 类型2字节对齐数是2,而int i对齐数是4字节,4不是14的倍数要对齐到4的倍数最后大小为16

在这里插入图片描述

三.枚举和联合体类型总结

本文介绍了两种c/c++中的自定义类型:枚举和联合体,继上篇->结构体类型 三种自定义类型已全部介绍
主要以认识,熟悉为主,在学的更深入之后,才会真正体会到设计这些自定义类型的好处…

在这里插入图片描述

相关文章:

  • 神经网络的梯度实现
  • 网络版本计算器(再谈“协议“)
  • C++——string的简单使用与深浅拷贝的理解(建议收藏)
  • BGP综合实验
  • Day4——两两交换链表节点、删除链表第n个绩点、链表相交、环形链表||
  • YOLOv5实现佩戴安全帽检测和识别(含佩戴安全帽数据集+训练代码)
  • H.264 入门篇 - 10 (帧间预测 - 参考帧列表修改/重排)
  • 第三章Linux环境基础开发工具使用(yum+rzsz+vim+g++和gcc+gdb+make和Makefile+进度条+git)
  • 博客系统数据库设计与实现之修改(java)
  • django-设置X-Frame-Options响应头防止点击劫持攻击
  • PostgreSQL自增主键的用法以及在mybatis中的使用
  • app逆向(10)| APP的加固与脱壳
  • 解析IEC 61850通信规约
  • 了解Selenium,看这一篇够了
  • 你就想这样一辈子躺平,还是改变这个世界?
  • 〔开发系列〕一次关于小程序开发的深度总结
  • Android交互
  • interface和setter,getter
  • JS 面试题总结
  • js递归,无限分级树形折叠菜单
  • leetcode378. Kth Smallest Element in a Sorted Matrix
  • mac修复ab及siege安装
  • Python学习之路13-记分
  • SpringBoot几种定时任务的实现方式
  • vue脚手架vue-cli
  • weex踩坑之旅第一弹 ~ 搭建具有入口文件的weex脚手架
  • 从setTimeout-setInterval看JS线程
  • 诡异!React stopPropagation失灵
  • 机器学习学习笔记一
  • 前端之Sass/Scss实战笔记
  • 如何使用Mybatis第三方插件--PageHelper实现分页操作
  • 吴恩达Deep Learning课程练习题参考答案——R语言版
  • 阿里云移动端播放器高级功能介绍
  • ​2021半年盘点,不想你错过的重磅新书
  • ​LeetCode解法汇总2182. 构造限制重复的字符串
  • # 20155222 2016-2017-2 《Java程序设计》第5周学习总结
  • #git 撤消对文件的更改
  • #if #elif #endif
  • #Z0458. 树的中心2
  • (MATLAB)第五章-矩阵运算
  • (超简单)构建高可用网络应用:使用Nginx进行负载均衡与健康检查
  • (待修改)PyG安装步骤
  • (第一天)包装对象、作用域、创建对象
  • (二)pulsar安装在独立的docker中,python测试
  • (离散数学)逻辑连接词
  • (三)uboot源码分析
  • (转)c++ std::pair 与 std::make
  • .php文件都打不开,打不开php文件怎么办
  • /usr/bin/env: node: No such file or directory
  • ?php echo $logosrc[0];?,如何在一行中显示logo和标题?
  • @RequestMapping用法详解
  • @selector(..)警告提示
  • [ Linux 长征路第二篇] 基本指令head,tail,date,cal,find,grep,zip,tar,bc,unname
  • [ 隧道技术 ] 反弹shell的集中常见方式(四)python反弹shell
  • [ 云计算 | AWS ] 对比分析:Amazon SNS 与 SQS 消息服务的异同与选择