话说enum

 

在C++中,如果一个变量你需要几种可能存在的值,那么就可以被定义成为枚举类型。之所以叫枚举就是说将变量或者叫对象可能存在的情况也可以说是可能的值一一例举出来。

但我并不想说enum怎么定义与怎么说明的,而要说的是enum在C++编译器中是如何处理的。我们先看一个例子:
enum D
{
B,
C
};

const char B = 'B';

int _tmain(int argc, _TCHAR* argv[])
{
return 0;
}

如果按照上面的程序进行编译,会得到如下的编译错误:
error C2365: 'B' : redefinition; previous definition was 'enumerator'
        c:\visual .net project\testenum\testenum\testenum.cpp(24) : see declaration of 'B'
错误的大致的意思是说枚举变量中的枚举元素B重复定义了,可事实上我们并没有定义两个枚举元素B,那是为什么呢?原因在于我们这个时候定义了一个全局的常量B。根据以上的编译错误,似乎我们可以得出一个这么一个结论:在全局作用域里有两个B的定义,且枚举元素B是作为单独变量进行编译的,不受enum D作用域的影响。另外,这个例子更容易出错的版本是这样的,定义两个enum,里面有相同的枚举元素:
enum D
{
B,
C
};

enum E
{
B
}

int _tmain(int argc, _TCHAR* argv[])
{
return 0;
}
继续,为了支持上述我的观点并深入研究编译器如何来编译枚举元素,我想通过dump一下看看.rdata区里是不是有一个这样的常量存在,所以我又写了一个这样的程序:
enum HardwareType
{
UNKNOWN = 1000
};

char * p = "Hello Kitty!";

int main()
{
HardwareType c = UNKNOWN;
return 0;
}
用VC++ 2005下自带的dumpbin工具对编译出来的obj文件进行分析,首先看.rdata段是否有这个常量的定义,这里要特别说明一下:一个Windows NT的应用程序典型地拥有9个预定义段,它是.text、 .bss、 .rdata、 .data、 .rsrc、 .edata、 .idata、 .pdata和.debug。这里不详细说每个段的具体含义,只简单说一下我们用到的段,.text段主要包含代码,.rdata段表示只读的数据,比如字符串文字量、常量和调试目录信息。.debug就是一些调试信息.
下面是dump出来的.rdata段的结果:
SECTION HEADER #3
  .rdata name
       0 physical address
       0 virtual address
       D size of raw data
     6E1 file pointer to raw data (000006E1 to 000006ED)
       0 file pointer to relocation table
       0 file pointer to line numbers
       0 number of relocations
       0 number of line numbers
40301040 flags
         Initialized Data
         COMDAT; sym= "`string'" (??_C@_0N@BKAKGEGI@Hello?5Kitty?$CB?$AA@)
         4 byte align
         Read Only

RAW DATA #3
  00000000: 48 65 6C 6C 6F 20 4B 69 74 74 79 21 00           Hello Kitty!.

如上面所示,在.rdata段里只有Hello Kitty!这个常量的数据,没有UNKNOWN的数据,因为1000对应的16进制数为:03E8,在.rdata段里找不到!但千万不要忘记了常量折叠的概念,这个在我上一篇文章中有解释,所以我们还要搜索.text和.debug段, 我们在这两个地方都找到了03E8这个值,出现这种情况只能够说明常量进行了折叠.但这种情况的出现还有两种情形,我觉得有必要再深入研究一下,一种是常量进行了折叠,另一种是预定义宏进行覆盖.所以我又写了一个程序进行了测试:
enum HardwareType
{
UNKNOWN = 1000
};

const int AAA = 100;

char * p = "Hello Kitty!";

int main()
{
&AAA;
&UNKNOWN;
return 0;
}
编译程序会出现如下的编译错误: error C2101: '&' on constant
这又说明了枚举元素UNKNOWN在编译器里的确是以常量来对待的,但它更像宏定义,感觉在预编译期就进行替代.但其实在预编译阶段并没有对枚举元素进行处理.这个原因我想以后说明。
所以综上所述,我们可以得出一个这样的结论: 枚举变量中的枚举元素在编译器中是按照常量来处理的,在所有出现枚举元素的地方你都可以认为它是一个整型常量,编译时枚举元素有名字,但你无法得到它的地址.

转载http://blog.youkuaiyun.com/stone_sky/article/details/7579706

 

      以上这是我查到的关于enum的资料,水平不够,不太了解,自己在vs2010实践,总结如下:

      1.枚举变量中的枚举元素在编译器中是按照常量来处理的,在所有出现枚举元素的地方你都可以认为它是一个整型常量,编译时枚举元素有名字,但你无法得到它的地址.

      2.我们在使用enum时候,可以把里面定义的常量的作用域当成一般的变量来看,这些常量作用域也会有文件作用局,文件静态作用域,局部作用域,

 

guyue

2013—7—27

<think> 我们正在讨论ENUM数据类型,用户要求用中文回答,并在最后提出3-5个相关问题。 根据之前的对话历史,用户已经给出了关于ENUM的示例(在Staff表中用于gender列),并且我们之前已经详细解释了ENUM和CHECK约束等。 现在用户直接输入“ENUM”,可能是希望更深入地了解ENUM类型本身,比如其优缺点、使用场景、注意事项等。 回答结构: 1. 首先解释ENUM的概念和作用。 2. 详细说明其优点和缺点。 3. 对比其他方法(如CHECK约束或外键引用)。 4. 提供使用示例。 5. 注意事项。 由于用户之前已经有一个Staff表的例子,我们可以在此基础上扩展。 注意:最后必须提出3-5个相关问题,以“§§相关问题§§”开头,并且问题要围绕ENUM展开。 </think> ### ENUM 数据类型深度解析 #### 📌 ENUM 的核心特性 ENUM 是数据库中的枚举类型,用于严格限制字段取值范围。以 `gender ENUM ('M', 'F', 'N', 'U')` 为例: - **值域控制**:仅允许存储预定义的选项(`'M'/'F'/'N'/'U'`) - **存储优化**:实际存储为整数索引(1字节),而非字符串 - **默认值支持**:可设置 `DEFAULT 'U'` 避免空值 - **强约束**:插入非法值(如 `'X'`)将触发错误: ```sql ERROR 1265 (01000): Data truncated for column 'gender' ``` #### ⚖️ ENUM 优缺点对比 | **优势** | **劣势** | |----------|----------| | ✅ 声明简洁直观 | ❌ 修改选项需重建表(MySQL) | | ✅ 存储高效(比VARCHAR节约50%空间) | ❌ 跨数据库兼容性差(Oracle/PostgreSQL不支持) | | ✅ 查询性能优化(整数索引加速) | ❌ 选项上限65535个(MySQL限制) | | ✅ 与程序枚举类型无缝对接 | ❌ 无法存储附加元数据 | #### 🔧 创建与操作示例 ```sql -- 创建含ENUM的表 CREATE TABLE Users ( id INT PRIMARY KEY, status ENUM('active', 'pending', 'banned') DEFAULT 'pending' ); -- 合法插入 INSERT INTO Users VALUES (1, 'active'); -- 成功 -- 非法操作 INSERT INTO Users VALUES (2, 'expired'); -- 错误1265 ALTER TABLE Users MODIFY status ENUM('active','inactive'); -- 需重建表 ``` #### 🚨 关键注意事项 1. **空值处理**: - `ENUM('A','B')` 可插入 `NULL` - 若需禁止空值需显式声明 `NOT NULL` 2. **排序陷阱**: ```sql SELECT * FROM Users ORDER BY status; -- 按索引值排序(active=1, pending=2, banned=3),非字母序 ``` 3. **迁移风险**: - 从MySQL迁移到PostgreSQL时需转换为 `CHECK(gender IN(...))` 约束 4. **索引机制**: - ENUM 自动创建隐藏的整数索引列 - `WHERE status='active'` 实际执行整数比较 #### ⚡ 适用场景建议 - **推荐使用** ✔️ 固定且极少变更的选项集(如性别/布尔状态) ✔️ 存储敏感型字段(节约空间优先) - **避免使用** ✖️ 需要频繁增减选项的场景 ✖️ 多语言应用(需关联本地化文本表) ✖️ 需要扩展元数据的字段
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值