在另一个问题中,我刚刚发现了C智慧的这颗小珍珠:
#define for if (false) {} else for
Run Code Online (Sandbox Code Playgroud)
这导致MSVC为一个非常有效的声明吐出"常量表达式"警告:
for (int i = 0; i <= 10; i++) {...}
Run Code Online (Sandbox Code Playgroud)
我理解为什么 MSVC抱怨,因为它扩展到:
if (false) {} else for (int i = 0; i <= 10; i++) {...}
Run Code Online (Sandbox Code Playgroud)
我只是不明白为什么开发人员会使用那个小片段.有人有想法吗?
Ada*_*eld 92
这是修复旧版Visual C++(v6.0及更早版本)中的错误.在过去,Visual C++已经破坏了关于在for语句中声明的变量的范围规则:
// This compiles in old versions of Visual C++, but it is in fact INVALID C++
for(int i = 0; ...)
{
...
}
for(i = 0; ...)
{
}
Run Code Online (Sandbox Code Playgroud)
换句话说,Visual C++给出i了一个范围,好像它是在循环之外声明的,它允许你在循环完成后继续使用它.这导致代码如上面的代码片段.在更多符合标准的编译器中,i不再在第二个for循环的定义范围内,因此编译器会发出有关i未定义的错误.
为了解决这个问题,有些人使用了这个宏(或非常相似的等效宏):
#define for if(0) {} else for
Run Code Online (Sandbox Code Playgroud)
这会将for循环更改为:
if(0)
{
}
else
for(int i = 0; ...)
{
...
}
Run Code Online (Sandbox Code Playgroud)
这会将for循环放入一个额外的范围级别,这样for无论Visual C++的bug如何,循环中声明的任何变量都将超出范围.这可以确保相同的代码在Visual C++和符合标准的编译器中一致地正确编译,并且不正确的代码无法一致地正确编译.
另请注意,如果宏被定义为:
// DO NOT USE
#define for if(1) for
Run Code Online (Sandbox Code Playgroud)
然后虽然这会对一些简单的代码产生相同的效果,但它会突然导致以下代码被错误地编译:
if(foo)
for(...)
{
...
}
else
doSomething();
Run Code Online (Sandbox Code Playgroud)
因为如果你扩展宏,你得到这个:
if(foo)
if(1)
for(...)
{
...
}
else
doSomething();
Run Code Online (Sandbox Code Playgroud)
而else现在与错误匹配if!因此,巧妙地使用if(0) {} else而不是if(1)避免这个问题.
作为最后一点,#define for if(0) {} else for不会导致无限递归,因为预处理器不会递归替换您当前定义的宏.在这种情况下,它只会做一次更换.
根据快速搜索,它是MSVC中的一个被克服的错误.
据我了解,
for(int i=0...){.....}
//later at the same scope level in the same function
for(int i=0...){...}
将导致重新定义'i'错误.
如果for语句包含在if语句中,则编译器按原样运行,以便不存在重定义错误(显然它解释'if'但不是'for'的范围级别)
| 归档时间: |
|
| 查看次数: |
7728 次 |
| 最近记录: |