游戏开发论坛

 找回密码
 立即注册
搜索
查看: 2144|回复: 7

令人费解的C/C++标准

[复制链接]

96

主题

529

帖子

539

积分

高级会员

Rank: 4

积分
539
发表于 2006-9-13 21:29:00 | 显示全部楼层 |阅读模式
偶然在一次编译中,发现编译器没有因为宏名的错误拼写报错,这引起了我强烈的好奇心,于是试着在VC++和g++几个编译器里试了以下代码:

#include <iostream>

int main()
{
#if ABCDEFG == FFFFFF
     std::cout << "test1"<< std::endl;
#endif

#if ABCDEFG == FFFFFF + 1
     std::cout << "test2"<< std::endl;
#endif

#if ABCDEFG + 1 == FFFFFF + 1
     std::cout << "test3"<< std::endl;
#endif

#if ABCDEFG + 5 == FFFFFF + 6
     std::cout << "test4"<< std::endl;
#endif

#if ABCDEFG + 6 == FFFFFF + 6
     std::cout << "test5"<< std::endl;
#endif

     return 0;
}

编译正常通过,输出结果:
test1
test3
test5

说明这几个编译器将未定义标识符设为某个固定的默认值,再次编码:
#include <iostream>

int main()
{
#if ABCDEFG == 0
     std::cout << "test1"<< std::endl;
#endif

#if FFFFFF == 0
     std::cout << "test2"<< std::endl;
#endif

#if ABCDEFG == 1
     std::cout << "test3"<< std::endl;
#endif

#if FFFFFF == 1
     std::cout << "test4"<< std::endl;
#endif

     return 0;
}

编译通过,输出结果为:
test1
test2

从而进一步证实:这几个编译器都将未定义标识符设为默认0值。

紧接着查看C++标准文档,在预编译指令章节中发现了关于未定义标识符的规定:
After all replacement due to macro expansion and the defined unary operator have been performed, all remaining identifiers and keywords, except for true or false, are replaced with number 0.

恍然大悟,原来是C++标准的规定。先前的疑问消释了,但很快另一个令人费解的问题也来了——为什么标准要这么规定?一个标准的制定,总该有它的理由,按照思维习惯,我们会禁不住想——这样做有什么好处?反正我是实在想不出在宏编译中碰到未定义标识符设为0会给程序员带来什么好处,而且我认为,这是条非常糟糕的标准定义!
既然在编译代码中要坚持而且必须要显式声明,为什么宏编译指令中碰到未定义标识符却将其置为0值,这本身就是一种怪异的不一致性,而且还隐藏着更致命的风险,试想一下以下的情况:
#if _MSC_VER == 1200
... //CODE
#endif
这段代码将在VC6中被编译。
但如果程序员因为疏忽,写了以下代码:
#if MSC_VER == 1200
...
#endif
MSC_VER是一个未定义的标识符而不是宏,它的值为0。很显然,这段代码将被忽略,由于开发者错误的宏名拼写,就是未定义的标识符和已定义的宏之间的差别。程序可能产生难以检查的异常现象,而开发者却难以凭直觉检查出来。。。
但遗憾的是,标准委员没制定“防呆”规范,反而似乎在鼓励这种"带着风险的自由",这并不是C/C++一贯的自由风格,因为此时的这个自由跟其他的自由不一样,它看起来没有任何的意义。
实在想不通,C++标准委员会为什么做出如此规定。这样的标准意义在哪呢?这样的标准有何合理之处?

89

主题

4036

帖子

4132

积分

论坛元老

Rank: 8Rank: 8

积分
4132
发表于 2006-9-13 23:06:00 | 显示全部楼层

Re:令人费解的C/C++标准

预处理不算是标准C++的吧?

140

主题

1228

帖子

1233

积分

金牌会员

Rank: 6Rank: 6

积分
1233
QQ
发表于 2006-9-14 08:46:00 | 显示全部楼层

Re:令人费解的C/C++标准

所以有个宏叫#ifdef
使用不可靠的代码是自己的问题吧。

96

主题

529

帖子

539

积分

高级会员

Rank: 4

积分
539
 楼主| 发表于 2006-9-14 09:25:00 | 显示全部楼层

Re: Re:令人费解的C/C++标准

xpertsoft: Re:令人费解的C/C++标准

预处理不算是标准C++的吧?


当然也是

96

主题

529

帖子

539

积分

高级会员

Rank: 4

积分
539
 楼主| 发表于 2006-9-14 09:27:00 | 显示全部楼层

Re: Re:令人费解的C/C++标准

lights: Re:令人费解的C/C++标准

所以有个宏叫#ifdef
使用不可靠的代码是自己的问题吧。


那每次碰到指令
...
#if CUR_SYSTEM == WIN32_SYS
...
#endif
时,都要扩写成:

#if defined CUR_SYSTEM && defined WIN32_SYS && (CUR_SYSTEM == WIN32_SYS)
...
#endif
不仅麻烦,而且还是没有能够满意地防止宏名被打错的情况:
#if defined CUR_SYSTEM && defined WIN32_SYS && (CUR_SYSTEM == WIN32_SY) //WIN32_SYS打成了WIN32_SY
...
#endif


7

主题

438

帖子

438

积分

中级会员

Rank: 3Rank: 3

积分
438
发表于 2006-9-14 11:06:00 | 显示全部楼层

Re:令人费解的C/C++标准

楼主的钻研精神值得鼓励。

不同的操作系统,不同的编译器,有不同的预定义宏。
接下去想一下,如果一个跨平台项目中引用了未定义的宏就导致编译错误,那么谁也别想用C语言的条件编译控制版本了。原因是什么,不会想不到吧?

0

主题

202

帖子

202

积分

中级会员

Rank: 3Rank: 3

积分
202
发表于 2006-9-15 22:51:00 | 显示全部楼层

Re:令人费解的C/C++标准

#ifdef 自己不用,后果自负

103

主题

1432

帖子

1458

积分

金牌会员

Rank: 6Rank: 6

积分
1458
QQ
发表于 2006-9-17 23:58:00 | 显示全部楼层

Re:令人费解的C/C++标准

确实有点问题。

但是如果,未定义为0,#ifdef 就比较好理解。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2026-1-25 11:33

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表