不应该执行中断时执行中断';T intmain(intargc,char*argv[]){ int i=0; 对于(i=0;i这个代码在编译编译器上编译不好,因为它是无效的C++(空main < /COD>)。

不应该执行中断时执行中断';T intmain(intargc,char*argv[]){ int i=0; 对于(i=0;i这个代码在编译编译器上编译不好,因为它是无效的C++(空main < /COD>)。,c++,if-statement,for-loop,break,C++,If Statement,For Loop,Break,与VS 2010一起编译和执行(与VS 2008中的版本相同)。我在最后一行(右括号)放置了一个断点,并通过调试器查看变量I。此代码将i保留为0。为什么? int main(int argc, char *argv[]) { int i = 0; for (i = 0; i < 50; i++) if (false) break; } intmain(intargc,char*argv[]){ int i=0; 对于(i=0;i < P>这个代码在编译编译

与VS 2010一起编译和执行(与VS 2008中的版本相同)。我在最后一行(右括号)放置了一个断点,并通过调试器查看变量I。此代码将i保留为0。为什么?

int main(int argc, char *argv[]) {
    int i = 0;
    for (i = 0; i < 50; i++)
        if (false) break;
}
intmain(intargc,char*argv[]){
int i=0;
对于(i=0;i<50;i++)
如果(假)中断;;
}
在此之后-请注意break之后的第二个分号-i如预期的那样为50


有人能解释一下这个奇怪的行为吗?< /P> < P>这个代码在编译编译器上编译不好,因为它是无效的C++(<代码>空main < /COD>)。 也就是说,

i
的结果值是不相关的:编译器可以做它想做的任何事情


原因是
i
从未在循环外读取(其本身可证明没有效果),也没有声明
volatile
,因此编译器可以证明没有明显的副作用,无论使用
objdump-d-S查看生成的汇编代码时,
i的值是多少,我们都可以看到GDB跳过循环的可能原因:

int main(int argc, char *argv[]) {
    int i = 0;
    for (i = 0; i < 50; i++)
        if (false) break;;
}
0000000000 400584:
int main()
{
400584:55%按需付费
400585:48 89 e5 mov%rsp,%rbp
挥发性int i;
对于(i=0;i<5;i++)
400588:c7 45 fc 00移动$0x0,-0x4(%rbp)
40058f:eb 09 jmp 40059a
400591:8b 45 fc mov-0x4(%rbp),%eax
400594:83 C001添加$0x1,%eax
400597:89 45 fc mov%eax,-0x4(%rbp)
40059a:8b 45 fc mov-0x4(%rbp),%eax
40059d:83 f8 04 cmp$0x4,%eax
4005a0:0f 9e c0设定值%al
4005a3:84 c0测试%al,%al
4005a5:75个jne 400591
4005a7:b8 00 mov$0x0,%eax
if(false)
打破
}
4005ac:c9/Q
4005ad:c3 retq
4005ae:90无
4005af:90无
即使在编译时关闭了优化(
-O0
标记为g++),实际上也不会为循环体生成代码。这可能意味着GDB将把循环视为单个语句,并且不会正确地单步执行循环


我在MSVC10中使用了GCC版本4.4.5和GDB版本7.0.1。

,这是可复制的。我检查了拆卸。这似乎是pdb文件生成中的一个问题。返回循环开头的跳转指令与下一个源代码行混合在一起,就是这样。 如果按step键转到下一行,它将从return语句返回for循环的开头,并按预期执行循环50次。
.

如何检查
i
的值?是否启用了编译器优化?第二个示例中的额外分号是循环外的一个空语句,因此从编译器的角度来看,这意味着这两个循环完全相同。只需使用
g++
检查各种可能的组合,请始终查看
50
。当然,您没有发布完整的示例,所以我不能确定我的代码是否与您的相同。。。也许你用某种奇怪的方式打印出来……试着做一个完整的例子,其他人可以测试。请看,在for条件下(i<50),似乎正在读取“i”,但for循环正在优化,因为“i”在其他任何地方都不会被读取。@Nick是的,这就是我的意思。澄清…编辑了原始帖子并改变了主要方法。听起来似乎有道理。但在“真实代码”中,测试条件并不总是错误的,编译器也没有机会对其进行优化。尽管如此,for循环似乎总是在一个周期后退出,只是看起来它实际上中断了。尝试将for循环中的
i=0
更改为
i=-100
,即(i=-100;i<50;i++)
。在调试器中,
i
很可能仍然为零。一种解决方法是在循环体周围放置大括号,右大括号放在自己的行上。返回到循环开头的代码将与右大括号关联。如果可以复制,可以通过connect.microsoft.com存档,以便在将来的版本中修复。
0000000000400584 <main>:
int main()
{
  400584:   55                      push   %rbp
  400585:   48 89 e5                mov    %rsp,%rbp
    volatile int i;

    for (i = 0; i < 5; i++)
  400588:   c7 45 fc 00 00 00 00    movl   $0x0,-0x4(%rbp)
  40058f:   eb 09                   jmp    40059a <main+0x16>
  400591:   8b 45 fc                mov    -0x4(%rbp),%eax
  400594:   83 c0 01                add    $0x1,%eax
  400597:   89 45 fc                mov    %eax,-0x4(%rbp)
  40059a:   8b 45 fc                mov    -0x4(%rbp),%eax
  40059d:   83 f8 04                cmp    $0x4,%eax
  4005a0:   0f 9e c0                setle  %al
  4005a3:   84 c0                   test   %al,%al
  4005a5:   75 ea                   jne    400591 <main+0xd>
  4005a7:   b8 00 00 00 00          mov    $0x0,%eax
        if (false)
            break;
}
  4005ac:   c9                      leaveq 
  4005ad:   c3                      retq   
  4005ae:   90                      nop
  4005af:   90                      nop