扒一枚举这个怪胎

2024-01-05 11:41
文章标签 一枚 怪胎

本文主要是介绍扒一枚举这个怪胎,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

人生若只如初见:初识枚举

      第一次见到枚举,大家都会觉得很简单,很多资料都会告诉你,

枚举是C语言中的一种基本数据类型,

它由关键字enum+枚举类型标识名(标识符,自定义)+{枚举成员名1,枚举成员名2,枚举成员名3,枚举成员名4 }

enum Frame{cmd1=01,cmd2,stu1,stu2,};printf("输出枚举成员stu2的值%d\n",stu2);printf("输出枚举成员stu1的值%d\n",stu1);printf("输出枚举成员cmd2的值%d\n",cmd2);printf("输出枚举成员cmd1的值%d\n",cmd1);

输出的结果是:

1:枚举成员的特性(再识枚举,其实它也有自己的小脾气)

     也就是说,枚举成员=只能是整形,且只能是常量,以下几种情况都是对枚举成员的错误赋值

(一):枚举成员定义成字符串

     ,我们试一试将枚举成员cmd1设置为字符串cmd1="a",可以看到编译阶段直接报错。注意看cmd2='a',因为C语言中将字符型等价于整形(具体参考ASCIL码),是符合枚举成员的赋值策略的,这一点需要注意。

 (二):枚举成员定义为整形变量

我们试一试将枚举成员定义成变量,看看结果如何。

编译直接报错

(三):枚举成员定义为实形常量

编译就报错,这里还有一个点需要注意,就是大量的资料里都将enum和预定义命令#define作比较。认为二者在功能实现上有相似之处。通过上面的例子可以看出。

#define stu1 1.2    是合法预定义指令

enum Frame{stu1=1.2} ;是不合法语句,需特别注意

总结:枚举成员具有在赋值上,具有如下属性

1:必须是常量,必须是整形常量(整形常量和合法ASCIL字符都可以),且是默认为是有符号整形常量。

2:枚举有自赋值属性和自增属性,且看如下属性

1:如果定义枚举类型时,如果不对枚举成员赋值,则从左起第一个枚举成员默认为0

2:枚举成员第一个值赋值后,从左往右,枚举成员的值依次+1

1:举例说明

#include <stdio.h>
#include <stdlib.h>int main()
{   int a =10;enum Frame{stu1,stu2,cmd1,cmd2};printf("输出枚举成员stu1的值%d\n",stu1);printf("输出枚举成员stu2的值%d\n",stu2);printf("输出枚举成员cmd1的值%d\n",cmd1);printf("输出枚举成员cmd2的值%d\n",cmd2);return 0;}

2:举例说明

#include <stdio.h>
#include <stdlib.h>int main()
{   int a =10;enum Frame{stu1=-3,stu2,cmd1,cmd2};printf("输出枚举成员stu1的值%d\n",stu1);printf("输出枚举成员stu2的值%d\n",stu2);printf("输出枚举成员cmd1的值%d\n",cmd1);printf("输出枚举成员cmd2的值%d\n",cmd2);return 0;

 输出结果如上图

这里需要注意一点,枚举成员是可以赋值负数的,但是如果执行如下代码,定义一个unsigned char变量a,再把stu1,赋值给a,编译运行后就会出现错误。这里涉及到负数以补码的形式存储,和C语言隐形转换的知识,这里不细讲!有时间可以,另外写单独写。

int main()
{   unsigned char a =10;enum Frame{stu1=-3,stu2,cmd1,cmd2};a = stu1;printf("输出枚举成员stu1的值%d\n",stu1);printf("输出枚举成员stu2的值%d\n",stu2);printf("输出枚举成员cmd1的值%d\n",cmd1);printf("输出枚举成员cmd2的值%d\n",cmd2);printf("输出a的值%d\n",a);return 0;}

3:枚举成员,也是可以独立赋值

#include <stdio.h>
#include <stdlib.h>int main()
{   unsigned char a =10;enum Frame{stu1=-3,stu2='a',cmd1=9,cmd2=1};//char b =(char) a;a = stu1;printf("输出枚举成员stu1的值%d\n",stu1);printf("输出枚举成员stu2的值%d\n",stu2);printf("输出枚举成员cmd1的值%d\n",cmd1);printf("输出枚举成员cmd2的值%d\n",cmd2);printf("输出b的值%d\n",a);return 0;

可以看出,如果存在必要,可以单独对枚举成员单独赋值,只是情况非常少见。

聊聊enum的两个表亲

2.1:聊聊enum 的表亲 #defined

#define a1 3
enum{a2=3};

两者实现的功能是相同的。但是enum和#define是表亲关系,就像你和你姑姑家的表弟。血缘关系还要往上两代,所以它们之间有共同点,但是不多!在实际应用中,没有谁更好用,谁的优点更明显,只有根据项目需求合理应用。

#define a1 "a1"  //替代字符串#define a3(y) y*y //带参数宏代替
#define a4 3.14159 //a4代替实形常量
#define a5 a4     //宏定义的嵌套
#ifndef a6        //
#define a6 8
//等等

以上都是枚举无法执行的操作,切记枚举成员只能是整形常量。

2.2:enum 的另外一个表亲struct

      如果说#define是和enum是性格(理解为作用有相似之处),那enum的另外一个表亲struct就只是和和enum长得有点像罢了(理解成代码书写方式),实际上,他们之间的区别还是很大的。

typedef enum SexMessage
{female=1,male}
BoyOrgirl;
BoyOrgirl enum1_SexMessage=female;typedef struct MessageOfClass  //班级信息
{ int age;     //年级float Height; //身高int sex;      //性别char name[20]; //姓名
} studentmessage;studentmessage struct1_student1 = {20 ,15.8,female,"zhangsan"};

       注意观察以上代码!我们声明和定义声明了一个枚举类型,定义了性别信息。定义声明了一个枚举变量,并赋值给这个枚举变量。定义声明了一个结构体类型, MessageOfClass  //班级信息,并定义了一个结构体变量,赋值了结构体变量。

用来你就能理解为什么我说struct是也是enum的表亲了。

1:首先它们都能使用typedef(类型重定义)指令,指令格式typedef +(结构体or枚举)+重定义类型名

2:它们都能声明变量,枚举能声明枚举变量BoyOrgirl enum1_SexMessage;结构体能声明结构体变量,studentmessage struct1_student1

注意:声明的结构体变量,和声明枚举变量,它们在结构,赋值方式,占用内存大小方面都有很大不同:

枚举变量一次只能赋一个值,最好是使用已定义枚举类型里面的枚举成员

BoyOrgirl enum1_SexMessage=female;

      如果结构体变量想赋其他值,如:”BoyOrgirl enum1_SexMessage=100;一般情况下,编译器也不会报错,但是最严谨的写法应该加上一个强制转换BoyOrgirl enum1_SexMessage=(enum SexMessage)100

我们来试一试

#include <stdio.h>
#include <stdlib.h>
#define pi 3.14159
#define pi2 pi
typedef enum SexMessage
{female=1,male}
BoyOrgirl;
BoyOrgirl enum1_SexMessage=(enum SexMessage)100;
int main()
{printf("输出枚举变量enum1_SexMessage的值%d\n",enum1_SexMessage);printf("输出枚举变量enum1_SexMessage的大小%d\n",sizeof(enum1_SexMessage)); //输出枚举变量的大小
}

输出结果是100。

再试试看看此时枚举变量的大小

    此时我们再来填一个坑,就是我们已经知道了,枚举变量的大小是4Byte,我们试一下BoyOrgirl enum1_SexMessage=(enum SexMessage)0xFFFFFFFF;

#include <stdio.h>
#include <stdlib.h>
#define pi 3.14159
#define pi2 pi
typedef enum SexMessage
{female=1,male}
BoyOrgirl;
BoyOrgirl enum1_SexMessage=(enum SexMessage)0xFFFFFFFF;
int main()
{printf("输出枚举变量enum1_SexMessage的值%d\n",enum1_SexMessage);printf("输出枚举变量enum1_SexMessage的大小%d\n",sizeof(enum1_SexMessage)); //输出枚举变量的大小
}

看结果

       发现到了吗?输出enum1_SexMessage=-1,结合之前我说枚举可以是负值的。我们就可以得出结论了:枚举变量4Byte的最高位是符号位。

     这里仅看枚举变量最高字节,Byte4 = 0xFF ,展开为2进制 1111 1111 ,编译器识别最高位为1,判定为负数,负数需要转换为补码 (如果不知道具体转换方式,可百度)存储在RAM中,

      存储的形式 (1000 0000、 0000 0000、 0000 0000、0000 0001)于是当我们再次取出该值时,将该值打印出来就是=-1;类比int型变量 能表示的范围(-0x7F FF FF FF-->+0x7F FF FF FF)枚举变量能正确表示的范围也是(-0x7F FF FF FF-->+0x7F FF FF FF)。

       有兴趣的朋友,可以在去试试枚举成员 female的大小和能表示的范围大小。结论和结构体变量一致。都是4Byte ,表示范围是(-0x7F FF FF FF-->+0x7F FF FF FF)。

如果有极端情况下

你定义了一个枚举enum Enum2{a1,a2,............a9999999999999999999999}试想一下这样行不行。

再来看看,结构体

struct这个enum的老表,很多书籍和资料都说的比较透彻。我们可以自行查阅资料。

1:结构体类型在定义时,只对成员做类型说明,不能赋值。枚举只是做一个简单的替换,枚举里面的成员不做类型说明。成员赋值也不能理解为是C语句中的赋值,因为枚举定义时,实际上也是一种预处理命令,说人话就是他是给编译器看的,给编译器写的代码。

2:结构体变量才会占用内存,同样的枚举,也只是枚举变量才会占用内存,枚举定义时不占用内存

3:结构体可以嵌套结构体,而枚举不可以。且需要特别注意,实测发现结构体内,不能包含枚举

4:注意结构体变量和枚举变量的区别(主要指所占用空间的大小),结构体变量存在对齐原因。但是枚举变量固定为一个int的长度。

3.枚举在实际工程中的使用方法

枚举在实际工程中最常见的作用就是定义别名,类似于#define的作用。

如我们定义了一个监测温度的函数,函数根据温度放回一个状态,我们将状态分为如下几种

1)temperrature<-30℃时,返回verycool

2)-30℃<=temperrature<0℃,返回cool

3)0℃<=temperrature<25℃,warming

4)25℃<=temperrature<40℃ hot

5)25℃<=temperrature<50℃ very hot

首先,我们先定义一个函数原型,

由于我们放回的是字符串,由于C/C++中是没有返回值是字符串类型的函数,于是我们必须用数字代替。0代替verycool,1代替cool

如果使用#define verycool  1,要写5个很麻烦

这时就可以使用枚举了  enum TempureFlag{verycool,cool,warming,hot,veryhot};

函数类型,可以设施为

unsigned char Temperrature(void)  //注意这里有个小坑,函数原型最好设置为int

{

  int Tem;

   scanf("%d\n",Tem);

   if(Tem<-30)

       return veaycool;

........................

}

最后一段代码,是我自己为了以后方面查看,大家可以忽略。

#include <stdio.h>
#include <stdlib.h>
#define pi 3.14159
#define pi2 pi
typedef enum SexMessage
{female=1,male}
BoyOrgirl;
BoyOrgirl enum1_SexMessage=(enum SexMessage)0xFFFFFFFF;typedef struct MessageOfClass  //班级信息
{int age;                   //年级float Height;              //身高int sex;                   //性别char name[20];             //姓名
} studentmessage;
studentmessage struct1_student1 = {20,15.8,female,"zhangsan"};int print_enum_function(void)
{printf("输出枚举成员female的地址%p\n",female);printf("输出枚举成员male的地址%p\n",male);//printf("输出枚举标识符SexMessage的地址%p",SexMessage);printf("输出枚举变量enum1_SexMessage的地址%p\n",&enum1_SexMessage);}int main()
{unsigned char a =10;typedef enum Frame {stu1=-3,stu2='a',cmd1=9,cmd2=1};//char b =(char) a;a = stu1;printf("输出枚举变量enum1_SexMessage的值%d\n",enum1_SexMessage);printf("输出枚举变量enum1_SexMessage的大小%d\n",sizeof(enum1_SexMessage));printf("输出枚举成员female的大小%d\n",sizeof(female));printf("输出常量立即数的大小%d\n",sizeof(0xFFFFFFFF));printf("输出枚举成员stu1的值%d\n",stu1);printf("输出枚举成员stu2的值%d\n",stu2);printf("输出枚举成员cmd1的值%d\n",cmd1);printf("输出枚举成员cmd2的值%d\n",cmd2);printf("输出b的值%d\n",a);printf("下一步调用print_enum_function函数\n");print_enum_function();     //即使是是形式参数是void类型的,在调用时也要写上()括号return 0;}


————————————————
 

这篇关于扒一枚举这个怪胎的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/572750

相关文章

一枚程序员的爱情观,被一个我认为的浙江妹子一个渣渣,让我提高了我的认识,瞬间感觉人生在世,一定要去做些为往事开太平,立功立德立言,做一番成绩

我能做到疼你爱你,热恋时腻歪你,平淡期守护你。对爱感情专一、认真,坦诚相待,一辈子忠心爱你。不会朝三暮四。奔着结婚的目的好好疼你爱你,容忍你的小脾气,赚钱都给你花。同时我也要求你能够体谅我,爱我,陪我白头到老,共同经营爱情,不能随便的说分手,忠于爱情,不允许做出出轨的举动和背叛的事情。恋爱过程中,要互相理解,信任,宽容。对待恋爱要严肃认真,要对伴侣专一。有一个积极、乐观的心态。不要因为恐惧,

一枚门锁告诉我们:物联网时代的安全会是什么样子

一直以来,宅客君都有一个困惑:物联网时代下的安全会是神马样子的? 和电脑一样,有个杀毒软件?如手机一般,是个优化App?还是按以往传统路径,厂商全包全揽? 不知道。 宅客君曾在一次采访中请教对IoT推崇之至的红衣教主,不过对方非常罕见的“不谈案例谈趋势”,有些避而不答的味道。 最近,宅客君拜访一家物联网门锁厂商,又唤起了对这个问题的思考。 这家锁厂透露说,他们把传统机械锁的钥匙认证搬到云端

成为一枚优秀的创业者,必须学会画的三张脑图

创业是创业者对自己拥有的资源或通过努力能够拥有的资源进行优化整合,从而创造出更大经济或社会价值的过程。 我们知道创业开始会遇到很多困难,很多难点,但是只要留心不忽略每个细节然后整理出来总有云开见天日。 所以,想要做一枚优秀的创业者,应该懂得如何将创业构思一步步执行,这个时候就需要运用画图来理清思绪。 对于企业领导者来说,必不可少的三种图分别为思维导图,信息图,甘特图。 第一

在120枚外观相同的硬币中,有一枚是假币,并且已知假币与真币的重量不同,但不知道假币与真币相比较轻还是较重。可以通过一架天平来任意比较两组硬币,最坏情况下,能不能只比较5次就检测出这枚假币?

能 这道题目我想先通过另外一道题目引入我的方法: 在13枚外观相同的硬币中,有一枚是假币,并且已知假币与真币的重量不同,但不知道假币与真币相比较轻还是较重。可以通过一架天平来任意比较两组硬币,最坏情况下,能不能只比较3次就检测出这枚假币? 将13枚硬币分为三组 ABCD  EFGH  IJKLM 这里引入一个概念,每次天平倾斜方向称之为X方向、Y方向、和平衡 X方向不一定就是向左倾斜,

一枚卤蛋的集成产品开发

有一天,儿子回家说学校组织义卖活动,每位同学都要准备点什么东西来卖,收入捐给公益组织。根据义卖物品的种类,学生们分了图书组、文具组、百货组、食品组等,自由报名。我儿子报了食品组。我很不理解他为什么要报食品组。他不能因为自己是个吃货就报食品组啊,报食品组是要拿吃的去卖才行啊。儿子不想改报其他组,我们只能硬着头皮帮他准备吃的了。儿子还说,不能从超市买现成的,必须是自己亲自做的才行。无论如何,这个自主可

第3章第26节:常用图形:通过基本图形绘制一枚iPhone手机 [PowerPoint精美幻灯片实战教程]

本节演示如何通过基本图形,绘制一枚iPhone手机图标。 在此处按下并向右下方拖动,以绘制一个圆角矩形,作为手机的外壳。 将它的填充颜色设置浅灰色,和右侧的iPad的外壳的颜色相同。 接着来绘制手机的屏幕,首先在视图比例滑杆上点击,放大

VS2013连接MySQL5.6成功案例一枚

转载自:http://www.jb51.net/article/84121.htm 这篇文章主要为大家分享了VS2013连接MySQL5.6成功案例一枚,很有实用性,感兴趣的小伙伴们可以参考一下 如何在VS2013下对MySQL5.6进行连接,本文为大家提供了解决方案,供大家参考,具体内容如下 环境:win832系统,VS2013,MySQL5.6,boost1.60 需

2023年一枚平凡但不平庸技术宅的年终总结

2023年一枚平凡但不平庸技术宅的年终总结 文章目录 2023年一枚平凡但不平庸技术宅的年终总结过去一年的故事一月二月三月四月五月六月七月八月九月十月十一月十二月 达成的小目标博客锻炼旅行加班 2024年目标 过去一年的故事 2023年,经历非常多的小故事: 与同事相约野外徒步与大学实验室师弟们约饭回老家过年大年初一约上亲人自驾游新兴大年初二到街上看舞狮与村子的兄弟相约

GUI小游戏一枚

原文:GUI小游戏一枚 源代码下载地址:http://www.zuidaima.com/share/1550463720688640.htm 小游戏一枚、还是重在对java设计原则的理解、希望大家多多提出建议、谢谢 游戏主界面 运行com.leng.frame.GameStartFrame.java,有很酷的声音效果,不错。 游戏中 Game Over

愚蠢的怪胎技巧:从Outlook浏览Web

Most of us spend a painful amount of time in Microsoft Outlook, reading emails from the pointy-haired bosses and sending TPS reports around. Since you’re already in Outlook, why not browse the web a