#define for(int z=0;z<2;++z)for(int z=0;z<2;++z)for 中的第三个 'for' 是什么意思

What does third 'for' mean in #define for for(int z=0;z<2;++z)for

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

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

它将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 所提到的,它也是未定义的行为,这意味着就标准而言,任何事情 都可能发生。从“看似有效”的代码到成熟的 World War III 与火星人(他们入侵地球以清除丑陋的代码)。

预处理器替换发生在单次传递中,不支持递归。所以第二个 "for" 可能是为了链接现有的 "for" 循环,在它们前面加上宏 "for" 循环部分。

#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)
    {
       // ...
    }

预处理器的使用非常疯狂。

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

Sergey Tachenov 的最佳答案真的很棒,但还应该提到的是,这个宏确实使 every 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
    }
}

从这里开始只会变得更糟。考虑一个像

这样的无限循环
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
    }
}

如果满足条件,这会使您跳出内部无限循环....只能立即返回。现在您可能会陷入无限循环。

意外行为是避免某些事情的一个很好的理由,像这样的宏恶作剧非常危险,并且可能是一个真正的 b**ch 调试。想象一下,如果某些 include 指令将此移植到多个头文件中......