什么是第三个&#39; for&#39;表示在#define中为(int z = 0; z <2; ++ z)表示

时间:2016-04-08 18:54:47

标签: c++ c-preprocessor

我在C ++程序中找到了一段代码,似乎它在这个程序中每个for()循环循环两次,但为什么在这样的预处理器定义中需要这第三个呢?

#define for for(int z=0;z<2;++z)for

3 个答案:

答案 0 :(得分:9)

它将for替换为for(int z=0;z<2;++z)for。显然,那会转向

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

for (int z=0;z<2;++z) for (int i = 0; i < N; ++i) {
    // ...
}

因此创建了两个嵌套循环。没有额外的for,它将是

for (int z=0;z<2;++z) (int i = 0; i < N; ++i) {
    // ...
}

这显然是不正确的。

请注意,尽管您在问题中提供的表格中“正确”,但这并不意味着它是“良好做法”。这是过度宏滥用的一个例子,必须可以避免。以下是它可能出错的众多例子中的一个:

for (int z = 0; z < 5; ++z) {
    for (int i = 0; i < 3; ++i) {
        std::cout << z << std::endl; // this will never print 2, 3, 4
    }
}

这将扩展为

for (int z=0;z<2;++z) for (int z = 0; z < 5; ++z) {
    for (int z=0;z<2;++z) for (int i = 0; i < 3; ++i) {
        std::cout << z << std::endl; // this will never print 2, 3, 4
    }
}

意味着您现在有四个嵌套循环,并且内部循环将打印“不可见”z而不是您在外部循环中声明的z (它成为扩展代码中的第二级循环)。

另一个原因:正如@stefan指出的那样,使用关键字或其他众所周知的标识符作为宏名称是一个非常糟糕的主意。让人想起臭名昭着的#define true false。并且,正如@HolyBlackCat所提到的,它也是未定义的行为,这意味着就标准而言,任何都可能发生。从“似乎正在工作”的代码到与火星人一起全面爆发的第三次世界大战(他们邀请地球从丑陋的代码中清除它)。

答案 1 :(得分:2)

首先,这个宏是我见过的最丑陋的东西。我不建议做这样的事情。

Sergey Tachenov的最佳答案非常棒,但也应该提到这个宏确实让每个 for循环运行两次。这意味着下面显示的双重嵌套循环将执行400次(而不是200次)!这可能是意料之外的。

for (int i = 0; i < 10; i++) {
    for (int j = 0; j < 10; j++) {
        // I'll be executed 100 times without the macro
    }
}

变为

for (int z=0;z<2;++z) for (int i = 0; i < 10; i++) {
    for (int z=0;z<2;++z) for (int j = 0; j < 10; j++) {
        // I'll be executed 400 times with the macro
    }
}

这只会变得更糟。考虑像

这样的infinte循环
int some_condition = 0;
for(;;) {
    // insert logic here for calculating whether to break out
    if (some_condition) {
        some_condition = 0; // set back to false for use down the line
        break;
    }
}

变成

int some_condition = 0;
for (int z=0;z<2;++z) for (;;) {
    // insert logic here for calculating whether to break out
    if (some_condition) {
        some_condition = 0; // set back to false for use down the line
        break; // gets me out of for(;;)...but the outer loop repeats
    }
}
如果满足条件,

会使你从内在的无限循环中挣脱出来......只是回到它里面。现在你可能陷入无限循环。

意外的行为是避免某些事情的一个很好的理由,像这样的宏观诡计是非常危险的,并且可能是一个真正的调试。想象一下,如果有一些include指令将这个移植到几个头文件深处......

答案 2 :(得分:0)

预处理器替换在一次传递中发生,并且不支持递归。所以第二个&#34; for&#34;对于链接现有的&#34;以及#34;循环,用宏来预先设置&#34; for&#34;循环部分。

#define for for(int z=0;z<2;++z)for

因此它取代了

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

for(int z=0;z<2;++z)
    for (int i = 0; i < N; ++i)
    {
       // ...
    }

这对预处理器来说非常疯狂。