Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
295 views
in Technique[技术] by (71.8m points)

c - What is the possible use for "#define for if (false) {} else for"?

In another question, I just spotted this little pearl of C wisdom:

#define for if (false) {} else for

which caused MSVC to spit out "constant expression" warnings for a quite valid statement:

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

I understand why MSVC is complaining because it expands to:

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

I just don't understand why the developers would use that little snippet. Anyone have an idea?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

It's to fix a bug in old versions of Visual C++ (v6.0 and earlier). In the past, Visual C++ had broken scope rules about variables declared inside for statements:

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

for(i = 0; ...)
{

}

In other words, Visual C++ gives i a scope as if it were declared outside the loop, and it lets you continue using it after the loop is done. This lead to code such as the above snippet. In more standards-compliant compilers, i is no longer in scope at the definition of the second for loop, so the compiler issues an error about i being undefined.

To fix this, some people used this macro (or very similar, equivalent macros):

#define for if(0) {} else for

This changes the for loop into this:

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

This puts the for loop into an extra level of scope, so that any variables declared in the for loop will be out of scope afterwards, regardless of Visual C++'s bug. This makes sure that the same code compiles correctly consistently in both Visual C++ and standards-compliant compilers, and that incorrect code does not compile correctly consistently.

Also note that if the macro were instead defined as so:

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

Then although that would have the same effect for some simple code, it would suddenly cause the following code to be compiled incorrectly:

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

Because if you expand the macro, you get this:

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

And the else now matches up with the wrong if! So, the clever use of using if(0) {} else instead of if(1) avoids this problem.

As a final note, #define for if(0) {} else for does not cause infinite recursion, because the preprocessor will not recursively replace the macro which you are currently defining. It will only do one replacement in this case.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...