for循环中的奇怪行为-一个bug

strange behavior in for loop - a bug?

本文关键字:一个 bug 循环 for      更新时间:2023-10-16

我在Windows 7机器上使用Visual Studio 2012工作,当尝试运行以下代码片段(在x64模式下使用默认VC11 c++编译器编译)时,断言失败,这意味着,内部循环从未进入:

void loopTest1()
{
    const unsigned int k = 1;
    for (int m=0; m<3; ++m)
    {
        int acc = 0;
        for (int n=m-k; n<=m+k; ++n)
        {
            if (n<0 || n>=3) continue;
            ++acc;
        }
        assert (acc>0);
        cout << "acc: " << acc << endl;
    }
}

现在我改变了内循环的结束条件:

void loopTest2()
{
    const unsigned int k = 1;
    for (int m=0; m<3; ++m)
    {
        int acc = 0;
        int l = m+k; // this line was added
        for (int n=m-k; n<=l; ++n) // m+k was replaced by l
        {
            if (n<0 || n>=3) continue;
            ++acc;
        }
        assert (acc>0);
        cout << "acc: " << acc << endl;
    }
}

然后我得到正确的结果:

acc: 2
acc: 3
acc: 2

当我用硬编码的1替换const unsigned int k时,它也可以工作:

void loopTest3()
{
    //const unsigned int k = 1;
    for (int m=0; m<3; ++m)
    {
        int acc = 0;
        for (int n=m-1; n<=m+1; ++n) //replaced k with 1
        {
            if (n<0 || n>=3) continue;
            ++acc;
        }
        assert (acc>0);
        cout << "acc: " << acc << endl;
    }
}

编译器执行一些错误的优化吗?或者有什么具体的原因,为什么第一种情况下的行为至少是出乎意料的?

您的int m将被提升为unsigned int。在第一个循环中,这意味着m-k作为无符号值等于-1,这是最大的无符号值,明显大于m+k(当比较n时,它被提升)。从正确的角度来看,您最终会得到n是-1的无符号表示,m+k是1。当然,当您将无符号-1存储到有符号整数中时,它会溢出,并且在技术上是未定义的行为。它很可能保留了它的-1表示,然后被提升回最大无符号值。

以下是第一次迭代的分类总结:

迭代1:
m: 0
凯西:1 u
N =m-k: -1u = Max int,存储为signed int
m + k: 1 u
N<=m+k -> Max int <= 1u

在第二个示例中,n与另一个有符号整数比较时没有提升,它比较两个有符号整数。