问题描述及原因
c语言代码中,如果出现枚举元素与宏定义命名相同,则编译会出现错误,例如下述.h文件中,用 typedef 关键字为 枚举数据类型 enum{FALSE=0, TRUE=!FALSE} 起了一个新的名字 bool.
typedef enum {FALSE = 0, TRUE = !FALSE} bool;
typedef enum {RESET = 0, SET = !RESET} FlagStatus, ITStatus, BitStatus, BitAction;
typedef enum {DISABLE = 0, ENABLE = !DISABLE} FunctionalState;
typedef enum {ERROR = 0, SUCCESS = !ERROR} ErrorStatus;
如果代码工程中,同时出现如下的宏定义与枚举变量重名,则编译会报错。原因是:
- 枚举数据类型中的枚举元素,是常亮,不是变量,因此枚举元素又称为枚举常量。如上述枚举数据类型bool中,枚举元素 FALSE=0, 因此FALSE就是常量0,是有值的。
- 既然系统已经在声明枚举类型时,指定了FALSE是一种枚举元素(常量0),则如果在对其进行宏定义 #define FALSE 0 就会出现编译错误。
//#ifndef TRUE
//#define TRUE 1
//#endif
//#ifndef FALSE
//#define FALSE 0
//#endif
//#ifndef SUCCESS
//#define SUCCESS 1
//#endif
//#ifndef ERROR
//#define ERROR 0
//#endif
//#ifndef ENABLE
//#define ENABLE 1
//#endif
//
//#ifndef DISABLE
//#define DISABLE 0
//#endif
枚举数据类型的用法:定义及变量声明
枚举是一种数据定型:
- 可以先进行定义,然后由该数据类型来声明变量。
enum DAY
{
MON=1, TUE, WED, THU, FRI, SAT, SUN
};
enum DAY tomorrow; //变量 tomorrow的类型为枚举( 数据类型)型enum DAY
enum DAY good_day, bad_day; //变量good_day和bad_day的类型均为枚举类型enum DAY
- 也可以类型定义与变量声明同时进行:
enum //跟第一个定义不同的是,此处的标号DAY省略,这是允许的。
{
saturday,
sunday = 0,
monday,
tuesday,
wednesday,
thursday,
friday
} workday; //变量workday的类型为枚举型enum DAY
- 还可以用typedel关键字来重命名枚举数据类型,并利用该别名进行变量声明:
typedef enum DAY // 此处DAY枚举类型名可省略
{
saturday,
sunday = 0,
monday,
tuesday,
wednesday,
thursday,
friday
} workday; //此处的workday为枚举型enum DAY的别名
枚举数据类型的易错概念
(1) 枚举型是一个集合,集合中的元素(枚举成员)是一些命名的整型常量,元素之间用逗号,隔开。
(2) DAY是一个标识符,可以看成这个集合的名字,是一个可选项,即是可有可无的项。
(3) 第一个枚举成员的默认值为整型的0,后续枚举成员的值在前一个成员上加1。
(4) 可以人为设定枚举成员的值,从而自定义某个范围内的整数。
(5) 枚举型可替代预处理指令#define。
(6) 类型定义以分号;结束。
(7) 同一个程序中不能定义同名的枚举类型,不同的枚举类型中也不能存在同名的命名常量。即枚举类型的枚举元素无论如何(对本工程文件内部而言)也不能重名。
(8) 对枚举型的变量赋整数值时,需要进行类型转换。
enum DAY { MON=1, TUE, WED, THU, FRI, SAT, SUN };//枚举数据类型定义
enum DAY yesterday, today, tomorrow;//枚举变量声明
yesterday = TUE; //枚举变量赋值
today = (enum DAY) (yesterday + 1); //强制类型转换
tomorrow = (enum DAY) 3; //类型转换
//tomorrow = 3; //错误
(9)既然枚举元素是常量,因此可用于函数返回
unsigned char func_test(void)
{
//user's code
return TRUE; //TRUE为枚举类型bool的枚举常量
}
补充知识: 宏定义、const、枚举常量的比较
- 编译器处理方式不同
#define是在预处理阶段对所定义的常量进行替换展开;
const是在编译运行阶段使用;
enum是程序运行时起作用;
- 分配内存不同
#define宏定义仅仅是替换和展开,并不进行内存的分配(宏定义不分配内存,常量的定义分配内存);
const常量编译器会分配内存,在堆或者栈;
enum常量存储在内存数据段的静态存储区。
延伸:在C语言里,const的含义是被称为一个不能被改变的普通变量,而在C++中其含义就不尽相同。C++中的const常量,C++编译器都会尽量避免const 常量的内存分配,只有当不得已的时候才会分配具体的内存空间给const变量。
- 类型检查
#define宏定义没有类型检查和安全检查,所以会导致边际效应,出现不可预知的错误;
const在编译阶段进行类型检查和安全检查;
enum在编译阶段进行类型检查,但是只能进行整形的定义;