“#define for if(false){} else for”有什么用?

另一个问题,我刚刚发现了这个C智慧的小珍珠:

#define for if (false) {} else for 

这导致MSVC吐出一个相当有效的陈述“常量expression式”的警告:

 for (int i = 0; i <= 10; i++) {...} 

我明白为什么 MSVC抱怨,因为它扩展到:

 if (false) {} else for (int i = 0; i <= 10; i++) {...} 

我只是不明白为什么开发人员会使用这个小片段。 任何人有一个想法?

这是为了修复旧版本的Visual C ++(v6.0及更早版本)中的错误。 过去,Visual C ++已经打破了在声明里面声明variables的范围规则:

 // This compiles in old versions of Visual C++, but it is in fact INVALID C++ for(int i = 0; ...) { ... } for(i = 0; ...) { } 

换句话说,Visual C ++给了i一个范围,就好像它是在循环之外声明的一样,它可以让循环完成后继续使用它。 这导致代码,如上面的代码片段。 在更符合标准的编译器中, i不再在第二个for循环的定义范围内,所以编译器会发出一个关于i未定义的错误。

为了解决这个问题,有些人使用这个macros(或者非常相似的macros):

 #define for if(0) {} else for 

这将for循环更改for

 if(0) { } else for(int i = 0; ...) { ... } 

这将for循环放入了一个额外的范围,所以在for循环中声明的任何variables都将超出范围,而不pipeVisual C ++的错误。 这可以确保相同的代码在Visual C ++和符合标准的编译器中都能正确编译,并且不正确的代码不能一致地编译。

另外请注意,如果macros定义如下:

 // DO NOT USE #define for if(1) for 

然后,虽然这将有一些简单的代码相同的效果,它会突然导致下面的代码编译不正确:

 if(foo) for(...) { ... } else doSomething(); 

因为如果你扩展macros,你会得到这个:

 if(foo) if(1) for(...) { ... } else doSomething(); 

而现在, else现在匹配错了! 所以,聪明地使用if(0) {} else而不是if(1)避免这个问题。

作为最后一点,# #define for if(0) {} else for不会导致无限recursion,因为预处理器不会recursion地replace当前定义的macros。 在这种情况下只能做一个replace。

根据快速search它是一个MSVC中的错误被克服。

据我了解,

 for(int i = 0 ...){.....} 
 //稍后在相同的作用域中处于相同的作用域级别
 for(int i = 0 ...){...}

将导致重新定义“我”的错误。

如果for语句被包含在一个if语句中,编译器就像它应该那样工作,这样就没有重定义错误(显然它将范围级别解释为“if”而不是“for”)

由于msvc编译器错误地处理默认情况下在for语句中声明的variables范围。 为了避免这种行为,你必须closures微软的扩展,然后使ms头文件不能编译。

我使用(是的,我仍然使用vs6)一个不会导致在vs6中的警告,尽pipe英特尔编译器仍然发现它。

 #define for switch(0) case 0: default: for 

我不记得我从哪里得到它,但我怀疑我发明了它;-)

我知道其他答案已经说了大部分这个,但popup窗口说,以确保你回答这个问题。

效果已经被描述了。

有它的原因是将C ++代码移植到MSVC。 或者,如果你希望你的C ++代码平台独立,这也是非常有帮助的。 例如,你在Linux / MacOSX上开发它,现在想在MSVC中编译它。

对于C ++本身也是非常有用的。 例如:

 for(std::set<Foo>::iterator i = myset.begin(); i != myset.end(); ++i) { // ... } for(int i = 0; i < N; ++i) { // ... } 

我已经看到了MSVC代码,通过做任何工作:

 for(std::set<Foo>::iterator i1 = myset.begin(); i1 != myset.end(); ++i1) { // ... } for(int i2 = 0; i2 < N; ++i2) { // ... } 

要么:

 {for(std::set<Foo>::iterator i = myset.begin(); i != myset.end(); ++i) { // ... }} {for(int i = 0; i < N; ++i) { // ... }} 

在这两种情况下(imo)都不是那么好。 而这个#define是一个小的黑客使MSVC行为更加标准。