Это нужно для исправления ошибки в старых версиях 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; ...)
{
}
Другими словами, Visual C++ дает i
область действия, как если бы она была объявлена вне цикла, и позволяет вам продолжать использовать ее после завершения цикла. Это приводит к коду, такому как приведенный выше фрагмент. В более совместимых со стандартами компиляторах i
больше не находится в области определения второго цикла for
, поэтому компилятор выдает ошибку о том, что i
не определено.
Чтобы исправить это, некоторые люди использовали этот макрос (или очень похожие эквивалентные макросы):
#define for if(0) {} else for
Это изменяет цикл for
на это:
if(0)
{
}
else
for(int i = 0; ...)
{
...
}
Это помещает цикл for
в дополнительный уровень области видимости, так что любые переменные, объявленные в цикле for
, впоследствии будут вне области видимости, независимо от ошибки Visual C++. Это гарантирует, что один и тот же код корректно компилируется как в Visual C++, так и в компиляторах, соответствующих стандартам, и что неверный код компилируется некорректно.
Также обратите внимание, что если бы вместо этого макрос был определен так:
// DO NOT USE
#define for if(1) for
Затем, хотя это имело бы тот же эффект для некоторого простого кода, это внезапно привело бы к неправильной компиляции следующего кода:
if(foo)
for(...)
{
...
}
else
doSomething();
Потому что если вы развернете макрос, вы получите это:
if(foo)
if(1)
for(...)
{
...
}
else
doSomething();
И else
теперь совпадает с неправильным if
! Таким образом, разумное использование if(0) {} else
вместо if(1)
позволяет избежать этой проблемы.
И последнее замечание: #define for if(0) {} else for
не вызывает бесконечную рекурсию, потому что препроцессор не будет рекурсивно заменять макрос, который вы сейчас определяете. В этом случае будет произведена только одна замена.
person
Adam Rosenfield
schedule
12.06.2009