话说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在编译器里的确是以常量来对待的,但它更像宏定义,感觉在预编译期就进行替代.但其实在预编译阶段并没有对枚举元素进行处理.这个原因我想以后说明。
所以综上所述,我们可以得出一个这样的结论: 枚举变量中的枚举元素在编译器中是按照常量来处理的,在所有出现枚举元素的地方你都可以认为它是一个整型常量,编译时枚举元素有名字,但你无法得到它的地址.

<think>我们正在讨论VBA中的Enum(枚举)类型。Enum用于定义一组相关的命名常量,使代码更易读和维护。在VBA中,Enum的声明语法如下:[Public |Private]Enum枚举名成员名1 [=常数值1]成员名2 [=常数值2]...EndEnum关键点:1.作用域:可以用Public或Private修饰,PublicEnum可以在整个工程中使用,PrivateEnum仅在其所在模块内有效。2.成员赋值:可以显式赋值(必须是常量表达式),也可以不赋值(默认从0开始,后续成员比前一个多1)。3.使用枚举:可以增加代码可读性,避免使用魔法数字。示例: ```vba'在标准模块中声明一个公共枚举PublicEnum DaysOfWeekSunday =1MondayTuesdayWednesdayThursdayFridaySaturdayEnd Enum'使用枚举SubPrintDay()Dim todayAs DaysOfWeektoday =TuesdayDebug.Print today'输出3(因为Tuesday是第三个,显式赋值Sunday=1,所以Monday=2,Tuesday=3)End Sub```枚举的优势:-提高代码可读性:使用有意义的名称代替数字。 -类型安全:声明为枚举类型的变量只能赋予该枚举的成员值。 -便于维护:修改枚举值只需在定义处调整。注意事项: -枚举的底层类型是Long,不能是其他类型。 -枚举成员的值在运行时不可修改。 §§相关问题§§1.如何在VBA中遍历枚举的所有成员?2.Public Enum和PrivateEnum的作用域范围具体有哪些不同? 3.枚举成员的值是否允许重复?如果允许会有什么影响? 4.在VBA中,如何将整数转换为枚举类型?</think>在 VBA 中,`Enum`(枚举)是一种**用户自定义数据类型**,用于定义一组相关的命名常量,使代码更清晰易读。核心特性和用法如下: ### 核心特性 1. **命名常量集合** - 将数字常量转换为有意义的名称 - 替代魔法数字(Magic Numbers),提升可读性 ```vba Enum FileAccessMode ReadOnly = 1 WriteOnly = 2 ReadWrite = 3 End Enum ``` 2. **自动赋值机制** - 未显式赋值时,首成员默认为 0,后续递增 1 ```vba Enum Colors Red ' 0 Green ' 1 Blue ' 2 End Enum ``` 3. **作用域控制** - `Public Enum`:工程全局可用 - `Private Enum`:仅模块内可用(默认) ### 实际应用场景 ```vba ' 声明枚举 Public Enum WebStatus Loading = 100 Success = 200 NotFound = 404 ServerError = 500 End Enum ' 使用枚举 Sub HandleResponse(code As WebStatus) Select Case code Case WebStatus.Success Debug.Print "请求成功" Case WebStatus.NotFound Debug.Print "资源不存在" End Select End Sub ' 调用示例 HandleResponse WebStatus.Success ' 输出"请求成功" ``` ### 优势与注意事项 ✅ **优势** - 代码自文档化(无需注释解释数字含义) - 编译时类型检查(避免无效值) - 智能提示支持(输入时自动显示成员) ⚠️ **注意** - 枚举成员必须是唯一的长整型(Long) - 不能动态修改枚举值(运行时固定) - 避免跨模块同名枚举(用模块名前缀区分)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值