|
本帖最后由 jianhong_wu 于 2017-7-16 13:09 编辑
第七十八节: typedef和#define和enum。
第七十八节_pdf文件.pdf
(92.03 KB, 下载次数: 1617)
【78.1 typedef和#define和enum。】
typedef称为“类型定义”,#define称为“宏定义”,enum称为“枚举”。三者都有“一键替换”的能力,但是应用的侧重点各有不同。请看下面的例子,要写一个函数,把学生的分数分为3个等级,第1等级是“优”(范围:“优”>=90分),第2等级是“中”(范围:70分<=“中”<90分),第3等级是“差”(范围:“差”<70分),实现此算法的函数需要一个输入口和一个输出口,用来输入分数和输出判断结果,判断的结果用三个数字常量0,1,2来表示,0代表“优”,1代表“中”,2代表“差”。代码如下:
- unsigned char GetGrade(unsigned char u8Score)
- {
- if(u8Score<70)
- {
- return 2; //2代表“差”
- }
- else if(u8Score>=70&&u8Score<90)
- {
- return 1; //1代表“中”
- }
- else
- {
- return 0; //0代表“优”
- }
- }
复制代码
上述代码没有添加任何“typedef,#define,enum”,是“素颜照”级别的原始代码。现在对上述代码做一些美容,加入“typedef,#define,enum”的元素,代码如下:
- #define BAD_MEDIUM 70 //宏定义。用BAD_MEDIUM来表示“差”和“中”分数的分界线
- #define MEDIUM_GOOD 90 //宏定义。用MEDIUM_GOOD来表示“中”和“优”分数的分界线
- typedef unsigned char u8; //用typedef为类型“unsigned char”增加一个名为“u8”的代言人
- enum {GOOD = 0,MEDIUM,BAD}; //用enum把“0,1,2”三个常量转换为“GOOD,MEDIUM,BAD”
- u8 GetGrade(u8 u8Score)
- {
- if(u8Score<BAD_MEDIUM) //等级分数分界线的判断
- {
- return BAD; //BAD就是常量2,代表“差”。
- }
- else if(u8Score>=BAD_MEDIUM&&u8Score<MEDIUM_GOOD) //等级分数分界线的判断
- {
- return MEDIUM; //MEDIUM就是常量1,代表“中”
- }
- else
- {
- return GOOD; //GOOD就是常量0,代表“优”
- }
- }
复制代码
代码赏析:
赏析片段一:
- #define BAD_MEDIUM 70 //宏定义。用BAD_MEDIUM来表示“差”和“中”分数的分界线
- #define MEDIUM_GOOD 90 //宏定义。用MEDIUM_GOOD来表示“良”和“优”分数的分界线
复制代码
这里,用宏定义#define来关联分界线判断的分数,给后续代码的升级维护带来了便捷,因为用户有可能会要求把“差”“中”“优”三者的分数线进行调整,这时直接更改70和90这个数值就可以实现分数线的调整。可见,宏定义#define经常用在涉及“分界线”判断的场合。
赏析片段二:
- typedef unsigned char u8; //用typedef为类型“unsigned char”增加一个名为“u8”的代言人
复制代码
用类型定义typedef为类型“unsigned char”增加一个名为“u8”的代言人,u代表unsigned的u,8代表此类型占用8位,比如unsigned char就是占用8位的unsigned类型,所以用u8。如果是16位的unsigned类型就用u16,32位则用u32,这都是单片机界的常用命名习惯。上述代码用了类型定义,今后代码中凡是想定义一个unsigned char变量,都可以直接用u8来替代。这样有两个好处:第一个好处,u8的字符个数明显比unsigned char少,省了敲代码的力气。第二个好处,方便代码在各种不同硬件平台上的移植,因为不同的单片机不同的编译器对unsigned char,unsigned int,unsigned long翻译所得的结果是不一样的,比如,51单片机的unsigned int是占用16位的,而很多32位单片机的unsigned int是占用32位的,它们的16位则用unsigned short int类型,而不是unsigned int。
当我们用51单片机写代码的时候,可以如下类型定义:
- typedef unsigned char u8;
- typedef unsigned int u16;
- typedef unsigned long u32;
复制代码
当我们用32位的单片机写代码的时候,可以如下类型定义:
- typedef unsigned char u8;
- typedef unsigned short int u16;
- typedef unsigned int u32;
复制代码
这样,当我们想把51单片机的代码移到32位的单片机上时,只需要修改类型定义typedef这部分的代码,就可以快速做到代码在不同编译器平台上的类型兼容。
赏析片段三:
- enum {GOOD = 0,MEDIUM,BAD}; //用enum把“0,1,2”三个常量转换为“GOOD,MEDIUM,BAD”
复制代码
用枚举enum把“0,1,2”三个常量转换为“GOOD,MEDIUM,BAD”英文单词,最大的好处就是方便代码的阅读和修改。再多补充一点枚举的基础知识,上述代码中,第一个英文单词GOOD,经过“GOOD = 0”这条初始化的语句后,等效于常量0,后面的MEDIUM和BAD则C编译器自动对它们进行“累加1”排序,所以MEDIUM和BAD分别为常量1,2,这是C语言的语法规则。枚举enum的应用侧重在某些涉及到“状态”的数据类型,但是也不绝对。
【78.2 enum和typedef的相结合。】
enum一旦搭载上typedef后,可以把各自的特性发挥得淋漓尽致,产生另外一种常见的用途,那就是“人造”数据类型的用途,这里的“人造”解读为“人为制造”之意。比如上述78.1的函数u8 GetGrade(u8 u8Score),输出接口接收的是u8类型,但是内部return返回的是枚举类型的“GOOD,MEDIUM,BAD”其中之一,而u8虽然也能接收和兼容常量“GOOD,MEDIUM,BAD”,但是总是感觉有点“类型不匹配”的“不适感”,如果想消除这点“不适感”,可以用enum和typedef相结合的办法,修改后代码如下:
- #define BAD_MEDIUM 70 //宏定义。用BAD_MEDIUM来表示“差”和“中”分数的分界线
- #define MEDIUM_GOOD 90 //宏定义。用MEDIUM_GOOD来表示“良”和“优”分数的分界线
- typedef unsigned char u8; //用typedef为类型“unsigned char”增加一个名为“u8”的代言人
- typedef enum {
- GOOD = 0,
- MEDIUM,
- BAD
- } Grade; //通过typedef 和enum的相结合,“人造”出一个新的数据类型 Grade。
- Grade GetGrade(u8 u8Score) //这里返回的类型是Grade,而“GOOD,MEDIUM,BAD”就是属于Grade
- {
- if(u8Score<BAD_MEDIUM) //等级分数分界线的判断
- {
- return BAD; //BAD就是常量2,代表“差”。
- }
- else if(u8Score>=BAD_MEDIUM&&u8Score<MEDIUM_GOOD) //等级分数分界线的判断
- {
- return MEDIUM; //MEDIUM就是常量1,代表“中”
- }
- else
- {
- return GOOD; //GOOD就是常量0,代表“优”
- }
- }
复制代码
【78.3 例程练习和分析。】
为了熟悉typedef,#define,enum的用法,现在要写一个函数,把学生的分数分为3个等级,第1等级是“优”(范围:“优”>=90分),第2等级是“中”(范围:70分<=“中”<90分),第3等级是“差”(范围:“差”<70分),实现此算法的函数需要一个输入口和一个输出口,用来输入分数和输出判断结果,判断的结果用三个数字常量0,1,2来表示,0代表“优”,1代表“中”,2代表“差”。
- /*---C语言学习区域的开始。-----------------------------------------------*/
- #define BAD_MEDIUM 70 //宏定义。用BAD_MEDIUM来表示“差”和“中”分数的分界线
- #define MEDIUM_GOOD 90 //宏定义。用MEDIUM_GOOD来表示“良”和“优”分数的分界线
- typedef unsigned char u8; //用typedef为类型“unsigned char”增加一个名为“u8”的代言人
- typedef enum {
- GOOD = 0,
- MEDIUM,
- BAD
- } Grade; //通过typedef 和enum的相结合,“人造”出一个新的数据类型 Grade。
- Grade GetGrade(u8 u8Score); //函数声明
- Grade a; //“人造”出Grade类型的变量a,用来接收函数的判断结果。
- Grade b; //“人造”出Grade类型的变量b,用来接收函数的判断结果。
- Grade c; //“人造”出Grade类型的变量c,用来接收函数的判断结果。
- Grade GetGrade(u8 u8Score) //这里返回的类型是Grade,而“GOOD,MEDIUM,BAD”就是属于Grade
- {
- if(u8Score<BAD_MEDIUM) //等级分数分界线的判断
- {
- return BAD; //BAD就是常量2,代表“差”。
- }
- else if(u8Score>=BAD_MEDIUM&&u8Score<MEDIUM_GOOD) //等级分数分界线的判断
- {
- return MEDIUM; //MEDIUM就是常量1,代表“中”
- }
- else
- {
- return GOOD; //GOOD就是常量0,代表“优”
- }
- }
- void main() //主函数
- {
- a=GetGrade(98); //输入98分,a来接收判断的结果
- b=GetGrade(88); //输入88分,b来接收判断的结果
- c=GetGrade(68); //输入68分,c来接收判断的结果
- View(a); //在电脑端观察98分的判断结果a
- View(b); //在电脑端观察88分的判断结果b
- View(c); //在电脑端观察68分的判断结果c
- while(1)
- {
- }
- }
- /*---C语言学习区域的结束。-----------------------------------------------*/
复制代码
在电脑串口助手软件上观察到的程序执行现象如下:
- 开始...
- 第1个数
- 十进制:0
- 十六进制:0
- 二进制:0
- 第2个数
- 十进制:1
- 十六进制:1
- 二进制:1
- 第3个数
- 十进制:2
- 十六进制:2
- 二进制:10
复制代码
分析:
98分的判断结果a为0,0代表“优”。
88分的判断结果b为1,1代表“中”。
68分的判断结果c为2,2代表“差”。
【78.4 如何在单片机上练习本章节C语言程序?】
直接复制前面章节中第十一节的模板程序,练习代码时只需要更改“C语言学习区域”的代码就可以了,其它部分的代码不要动。编译后,把程序下载进带串口的51学习板,通过电脑端的串口助手软件就可以观察到不同的变量数值,详细方法请看第十一节内容。
|
|