博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
我只负责转换![C/C++]
阅读量:6677 次
发布时间:2019-06-25

本文共 1927 字,大约阅读时间需要 6 分钟。

我只负责转换![C/C++]

 

Written by Allen Lee

 

前不久,lsp在留下这样一个问题:

说明:

1.定义了一个枚举如下:

None.gif
enum
 _jb_prog_mode
ExpandedBlockStart.gifContractedBlock.gif
dot.gif
{
InBlock.gif    PROGRAM_ONE 
= 0,
InBlock.gif    PROGRAM_TWO
ExpandedBlockEnd.gif}
;
None.gif
None.gif
enum
 _jb_prog_mode e_prog_index;

2.疑惑:

None.gif
e_prog_index 
=
 (
enum
 _jb_prog_mode)
-
1
;

e_prog_index等于-1?为什么?

你的疑惑隐藏着这样一个结论:e_prog_index的值不应该等于-1。我相信你得出这个结论的理由是_jb_prog_mode枚举中没有哪个成员的值为-1,于是类型为_jb_prog_mode的变量e_prog_index的值也不应该为-1。

现在,我们转换一下场景,假定注册表中有如下的信息:

[HKEY_LOCAL_MACHINE\SOFTWARE\Allen]
"Name"="Allen Lee"
"ID"=dword:00000584

我们如何通过编程获取这些信息呢?我们可以使用Win32 API的RegQueryValueEx()函数来读取这些信息(代码片断):

None.gif
LPBYTE lpData;
None.gifDWORD dataBufLen;
None.gif
None.gif
if
 (RegQueryValueEx(hKey,        
//
 hKey为指向HKEY_LOCAL_MACHINE\SOFTWARE\Allen的句柄
None.gif
                    
"
Name
"
,
None.gif                    NULL,
None.gif                    NULL,
None.gif                    lpData,
None.gif                    
&
dataBufLen) 
==
 ERROR_SUCCESS)
ExpandedBlockStart.gifContractedBlock.gif
dot.gif
{
InBlock.gif    
// Convert_01:
InBlock.gif
    char* data = new char[dataBufLen];
InBlock.gif    data 
= (char*)lpData;
InBlock.gif    std::cout 
<< "User name: " << data << std::endl;
InBlock.gif
InBlock.gif
InBlock.gif    
// Convert_02:
InBlock.gif    
// DWORD* data = (DWORD*)lpData;
InBlock.gif    
// std::cout <
ExpandedBlockEnd.gif
}
None.gif
None.gif
if (RegQueryValueEx(hKey,
None.gif                    
"ID",
None.gif                    NULL,
None.gif                    NULL,
None.gif                    lpData,
None.gif                    
&dataBufLen) == ERROR_SUCCESS)
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
InBlock.gif    
// Convert_03:
InBlock.gif
    DWORD* data = (DWORD*)lpData;
InBlock.gif    std::cout 
<< "User ID: " << *data << std::endl;
InBlock.gif
InBlock.gif    
// Convert_04:
InBlock.gif    
// char* data = new char[dataBufLen];
InBlock.gif    
// char* data = (char*)lpData;
InBlock.gif    
// std::cout <
ExpandedBlockEnd.gif
}

留意这段代码有两次转换,如果我们分别把Convert_01和Convert_03替换为Convert_02和Convert_04的话会怎么样呢?编译器不会为难你的,但运行效果可想而知。

回顾这两个例子,我们可以得到什么结论呢?正如本文的题目——

我只负责转换!

当你强制把-1转换为_jb_prog_mode类型并赋值予e_prog_index变量时,你只能说e_prog_index变量不包含_jb_prog_mode枚举预定义的值,并不能说e_prog_index变量的值非法(其实枚举类型和整数类型之间有着很深的渊源)。编译器是不会妨碍你的这种转换,而这种转换是否有意义就是另外一回事了。当然,你应该采取某些措施来检测枚举变量是否包含预定义的值,否则你将可能不时收到意外惊喜。

在C/C++中,枚举其实是整数常量的一种表现形式,它实质上只是协助程序员标识一组相关的整数常量。语义上,

None.gifenum _jb_prog_mode
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
InBlock.gif    PROGRAM_ONE = 0,
InBlock.gif    PROGRAM_TWO
ExpandedBlockEnd.gif}
;

等效于

None.gifstatic const int PROGRAM_ONE = 0;
None.gif
static const int PROGRAM_TWO = 1;

C/C++给予程序员最大的自由来进行选择,这也体现出C/C++对程序员的信任。然而,这种信任究竟是帮助我们还是伤害我们,就要看程序员本身的做法了。

最后,我引用Robert B. Murray的一段话[1]结束本文:

写出依赖于语言中定义含糊、意义微妙的规则的程序是不好的,即便作者本人清楚它的意义并保证它可以正确运行,下一个来维护这段代码的人也可能未必能够做到这点。比较好的做法是:坚持使用语言中那些被广泛使用及理解的部分来写程序。

 

See also:

  • Allen Lee;
  • Allen Lee;
  • [1]

 

转载地址:http://fgyao.baihongyu.com/

你可能感兴趣的文章
市场活动课件:SQL Server 索引优化
查看>>
Linux程序包管理rpm命令的使用解析
查看>>
什么是证书颁发机构(CA)
查看>>
php-fpm定义成集群资源时报错解决方法
查看>>
FORM开发相关技术(二)
查看>>
实战DeviceIoControl 之一:通过API访问设备驱动程序
查看>>
MFC消息循环
查看>>
配置Spring数据源
查看>>
Jquery元素追加和删除
查看>>
QtWidget: 鼠标拖动窗口(没有标题栏时)
查看>>
数据挖掘
查看>>
Lightning Lessons 史上最蛋疼的英文题
查看>>
JS 实现图片预加载
查看>>
database link 使用<转>
查看>>
WPF换肤系列索引
查看>>
surfaceview 与 view 的区别
查看>>
JavaScript document属性和方法
查看>>
svn命令备份
查看>>
Linux下安装中文输入法
查看>>
嵌入式数据库Perst
查看>>