for循环中的奇怪行为 - 一个错误?

时间:2013-05-24 13:27:53

标签: c++ visual-studio-2012 compiler-construction

我正在使用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;
    }
}

编译器是否执行了一些错误的优化? 或者是否有任何具体原因,为什么第一种情况下的行为至少是意料之外的?

1 个答案:

答案 0 :(得分:3)

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

以下是第一次迭代的各种摘要:

  

迭代1:
  m:0
  k:1u
  n = m-k:-1u = max uint,存入signed int中   m + k:1u
  n&lt; = m + k - &gt; max uint&lt; = 1u

在第二个示例中,与其他有符号整数相比,n不会被提升,它会比较两个有符号整数。在你的第三个,没有任何未签名。