enum in c language

今天说说C语言中的枚举。

参考:Enumeration (or enum) in C

1 定义

定义一个枚举类型很容易:

enum aa { a1, a2, a3 };

这里

  • enum是关键字
  • aa是枚举变量,也就是我们自定义类型
  • a1,a2,a3是枚举成员

然后怎么使用呢?

首先,它就像结构体struct和联合体union那样,是一个自定义的数据类型,用它定义变量,也是一样的:

enum aa abc; 	// 定义变量
enum aa *en_p; 	// 定义指针

是的,它跟基本数据类型以及结构体等特殊数据类型一样,都可以定义变量和定义指针

所以,和int一样,如果仅仅定义,而没有赋值和使用,编译后它就没了,变量定义本身不占地方,赋值了才占地方。

另外,和struct一样,它只是一个结构,这个结构是C语言层级的声明,编译后不存在这个结构的,汇编层级没有的。

所以,下面我们先说说,变量的赋值

2 变量的赋值

枚举类型的赋值其实是比较复杂的,先说最常用的。

2.1 默认值

enum aa { a1, a2, a3 };

对于上述枚举类型,它的a1 a2 a3, 在默认情况下,会被赋值为

a1 = 0;
a2 = 1;
a3 = 2;

2.2 赋初值

enum aa { a1 = 1, a2 = 3, a3 = 5 };

可以对其任意赋初值,这样,三个枚举成员的值就对应了你指定的值了。

我们看看多种情况:

情况1:全都赋初值

enum aa { a1 = 1, a2 = 3, a3 = 5 };

情况2:有重复的初值

这种情况的完全可以的。

enum aa { a1 = 1, a2 = 1, a3 = 5 };

情况3:部分赋初值,部分不赋值

enum aa { a1 = 1, a2, a3 };

对于此时,a2 = 2 a3 = 3,也就是说,后面没有赋值的,是默认根据前面赋值的累加的

enum aa { a1 = 1, a2, a3, a4 = 10, a5, a6 };

那这种情况呢?

  • 根据a1累加:a2 = 2 a3 = 3 a4 = 4
  • 根据a4累加:a5 = 11 a6 = 12

赋值范围

与int类型赋值范围一样!赋值-1什么的也可以,与int类型的范围一样的。

2.3 变量赋值

其实就是定义一个变量,然后给它赋值,这里不一样的是,枚举成员本身,就代表值

enum aa { a1 = 1, a2, a3, a4 = 10, a5, a6 };
enum aa abc = a2;

这个时候,abc = 2a2就代表数值2.

从其他角度理解,enum aa abc = a2;的含义就是

int a2 = 2;
int abc = a2;

就是这么个意思。

2.4 指针赋值

enum aa abc = a2;  
enum aa *enu_p = &abc;
printf("%d\n", *enu_p);		

没啥好说的,跟基本数据类型指针待遇一样的。

3 谈谈枚举成员

3.1 作用范围

首先,结构体本身

enum aa { a1 = 1, a2, a3, a4 = 10, a5, a6 };

它的作用范围,跟struct一样,跟int也一样,{ } 里面就是局部变量,在最外面就是全局变量,对于aa这个自定义类型标识符,也是一样的,不多说了。

比较需要注意的是,枚举成员也是标识符

3.2 枚举成员也是标识符

我们上面的例子,a1,a2,a6这些,在其作用域内,也是标识符,也就是相当于你定义了一个int a1;一样,在作用域内不能重复定义了!并且,这个标识符本身代表了一个int值。

int main(){enum aa { a1 = 1, a2, a3, a4 = 10, a5, a6 };int a1; // error!重定义了!上面定义过a1了!enum bb {a2,a4}; // error!
}

4 enum与int

enum中的枚举成员,都是int类型的变量,也代表int类型的值,值的范围也是int的范围。

5 enum与#define

5.1 共同点

下面两段代码基本来说是等价的:

#define Working 0
#define Failed 1
#define Freezed 2
enum state  {Working, Failed, Freezed};

5.2 enum的优势

#define是全局的,而enum则是与基本数据类型一样,范围非常灵活。

5.3 #define的优势

enum只能定义int类型值,define什么都可以等价,任何值,以及函数,都可以。

6 enum的大小(size)

6.1 变量的大小

注意:讨论enum结构本身大小没必要,因为其变量,就是这个结构的实例化,这一点和struct一样的!

enum aa { a1 = 10, a2, a3 };
enum aa abc = a2;
printf("size = %d\n", sizeof(enum aa)); // 4 
printf("size = %d\n", sizeof(abc));		// 4

试一下就知到了,都是4字节。这俩肯定相等,一个是模板,一个是实例

为什么是4呢?

因为enum这里面的值,其实就是int类型的,那不就是4吗!然后这个枚举变量,值只能有一个吧,那就占一个4字节空间足够了。

像struct那是可以有多个值,所以每个变量都占空间,这个就没必要,一堆里面选一个就可以了。

另外就是,不要试图获取枚举成员的地址,因为它有没有用上场都不一定呢,它只是C语言层级的一个值而已,不一定被分配

在这里插入图片描述

好吧,没人这么闲的没事干。

7 奇奇怪怪

enum aa abc = 100;
printf("***%d\n", abc); // 100

这种情况下,就真的当int用了,其实也没啥,反正编译器允许,不过一般没人这么干。

8 最后,说说真正常用的地方

说实话,说了这么多,基本都很少用得到!常用的地方也就固定套路,内些野路子你看看就好。

就比如你定义个月份什么,星期什么的。

#include<stdio.h>enum year{Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec};int main()
{int i;for (i=Jan; i<=Dec; i++)      printf("%d ", i);return 0;
}

另外还有就是,编译原理中的,词法分析器的单词表,需要把编号和名称对应起来,enum是天然适合的结构,使用struct嵌套enum和其他,就很完美很方便。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/384607.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

信号量SIGCHLD的使用,如何让父进程得知子进程执行结束,如何让父进程区分多个子进程的结束

本教程基于 Ubuntu 20.10 gcc 10.2.0. 示例程序如果不能正常编译和执行&#xff0c;说明您系统和工具版本与我的不匹配&#xff0c;请自行查阅资料。 0 概述 先给出该信号的描述&#xff1a; SignalValueDescriptionSIGCHLD17Child status has changed (POSIX). Signal sent …

使用gdb调试多进程程序、同时调试父进程和子进程

参考: [1] GDB debugging multi-process programs [2] Debugging programs with multiple processes 根据这两篇参考链接&#xff0c;完全可以实现使用gdb同时调试父进程和子进程。 接下来说明一下可能遇到的坑 gdb8.1版本有bug&#xff0c;设置完set detach-fork-on off&…

Linux安装Ncurses库

参考&#xff1a;How To Install Ncurses Library In Linux 针对Ubuntu说明一下&#xff1a; wget https://ftp.gnu.org/pub/gnu/ncurses/ncurses-6.2.tar.gz&#xff0c;至于最新版本&#xff0c;自己看官网&#xff0c;修改一下版本号即可。tar xzf ncurses-6.2.tar.gzcd nc…

gdb 10.2的安装

参考 [1] GDB-10.2 [2] README for GDB release 个人系统 Ubuntu20.10。 注意gdb10.2需要c11语法&#xff0c;需要安装g 下载安装包wget https://ftp.gnu.org/gnu/gdb/gdb-10.2.tar.xz解压缩tar -xvzf gdb-10.2.tar.xz进入解压之后的目录mkdir buildcd build配置&#xff0c;…

gdb tui的使用

[1] GDB Text User Interface [2] GDB Text User Interface 简单来说&#xff0c;进入gdb之后&#xff0c;使用ctrl x 2就足够了。其他细节请参考上述链接&#xff0c;选一个就可以。

C语言中信号函数(signal)的使用

先来简单谈谈C语言中的信号&#xff08;signal&#xff09; 首先&#xff0c;signal是C语言库中的函数&#xff0c;它实际上是软中断&#xff0c;也就是软件发出的终端&#xff0c;本质来说&#xff0c;类似于int n。 对于接收到该软中断信号的进程&#xff0c;就会停下手头的…

UNIX哲学

参考&#xff1a; 对比Linux与Windows 使用Linux想要做某些事情的时候&#xff0c;就拆开想&#xff0c;想想我需要哪些功能&#xff0c;需要哪些工具&#xff0c;依次怎么执行&#xff0c;然后用管道建立连接&#xff0c;让数据依次流过不同的工具&#xff0c;从而得到最终结果…

fork创建多个子进程

references: [1] how to create two processes from a single Parent [2] fork() in C [3] linux中fork同时创建多个子进程的方法 fork的本质&#xff0c;就是复制&#xff0c;把当前进程复制一份&#xff0c;然后两个进程并发地执行fork后面的语句&#xff0c;区别就是&#x…

wait系统调用

reference:Wait System Call in C 只强调几点&#xff0c;剩下的直接看参考链接内容就好了&#xff0c;不是偷懒&#xff0c;而是里面内容写的很好了&#xff0c;没必要再写一遍了&#xff0c;这种东西就是单纯的系统调用而已&#xff0c;理解了功能&#xff0c;就完事了&#…

Linux进程间通信:共享内存与管道

references: [1] IPC through shared memory [2] Inter Process Communication (IPC) [3] https://www.geeksforgeeks.org/pipe-system-call/ [4] watch command in Linux with Examples 参考链接1和2是介绍了共享内存IPC的简单原理和相关系统调用的使用参考链接3是介绍了管道通…

find command基本使用

find命令通常用于根据文件名查找文件&#xff0c;这是最基本用法。 find [path] -name/-iname [filename] path写要查找的路径&#xff0c;自动递归查找filename写文件名&#xff0c;可以使用通配符*还有其他什么的表达式 具体细节请man find查阅文档。

正则表达式特别需要注意的点:“空“字符的匹配

在正则表达式中&#xff0c;[...]代表1个字符&#xff0c;不管里面有多少字符&#xff0c;最终这个东西的结果都是1个字符。 对于表达式[^a]表达的匹配除了a之外的字符&#xff0c;并且是1个字符。 需要注意的是&#xff0c;有些特殊字符是不会被匹配的。 我们看一个示例&am…

vim多列操作--插入/删除

插入 How to insert text at beginning of a multi-line selection in vi/VimVim Commands 删除 ctrl v使用上下左右键选中一片区域按d删除

vim进行行内某部分的复制剪切粘贴

ctrl v使用方向键选中你要复制的部分 按d&#xff08;剪切&#xff09;或者按y&#xff08;复制&#xff09;再移动到你的目标位置&#xff0c;按p粘贴&#xff08;在正常模式下才行&#xff0c;如果不是&#xff0c;先按esc&#xff09; 这个过程与你操作word文档的复制粘贴…

函数调用堆栈

基于孟宁老师的Linux内核分析 1 int g(int x){ 2 int y x 3;3 return y;4 }5 6 int f(int x){7 int z x 10;8 return g(z);9 }10 11 int main(){12 int a f(8) 1;13 return 0;14…

gdb调试的几点提示(1)

GDB debugger Examining Memory Continuing and Stepping How to translate a virtual memory address to a physical address? s和n是C语言的下一步 si和ni是汇编语言下一步 gdb能够查看的都是虚拟地址&#xff0c;不能查看物理地址&#xff0c;应用程序都不能查看物理地址…

C语言读取文件

C语言一次性读取文件 C - File I/O C library function - fread() 需要注意的点 fgets函数&#xff0c;一次只能读取一行&#xff0c;并且在结尾自动添加\0fread函数&#xff0c;可以读取很多内容&#xff0c;但是不会添加\0需要手动完成&#xff0c;具体看[参考1]

Vivado提高综合和实现的速度

让计算机的资源尽可能给vivado&#xff0c;综合、实现的时候修改一个参数 jobs改为你的计算机的最大值&#xff0c;我的计算机是12核的。 速度会快很多&#xff01;

安装Ubuntu RISC V toolchain失败(网速、git配置原因)

git获取大容量工程出错&#xff1a;RPC failed&#xff1b; curl GnuTLS recv error : Decryption has failed. error: RPC failed; curl 56 GnuTLS recv error (-54): Error in the pull function.fatal: The remote end 官方GitHub仓库 gitee镜像仓库 如果网速不够&#xff0…

Linux环境变量 set env export区别

参考链接 How to Set Environment Variables in Linux set 他能够显示当前shell的环境变量 它针对的对象是当前shell&#xff0c;如果关闭了就没了&#xff01; 直接使用set --help查看就可以。 env 显示当前用户的环境变量&#xff0c;针对的当前登录的用户 export 它能…