c++ - 增量优化掉(Visual C Express 2010)

标签 c++ compiler-optimization visual-c++-2010-express

在使用 Visual C++ Express 2010 处理 C++ 项目时,我发现了一个我想了解的有趣问题。问题是如果我在 Debug 或 Release 模式下编译,我的程序的结果是不同的。我做了一个小程序来重现它:

#include <stdio.h>


int firstarg(int i)
{
    printf("First argument called with i = %d\n", i);

    return i;
}

int secondarg(int i)
{
    printf("Second argument called with i = %d\n", i);

    return i;
}

void function(int i, int j)
{
    printf("Function called with %d, %d\n", i,j);
}

int main(int argc, char* argv[])
{

    // Line with the problem!
    for (int i = 0; i < 5; ) function(firstarg(i), secondarg(i++)); 

    return 0;
}

// Result on RELEASE:
Second argument called with i = 0
First argument called with i = 0
Function called with 0, 0
Second argument called with i = 1
First argument called with i = 1
Function called with 1, 1
Second argument called with i = 2
First argument called with i = 2
Function called with 2, 2
Second argument called with i = 3
First argument called with i = 3
Function called with 3, 3
Second argument called with i = 4
First argument called with i = 4
Function called with 4, 4

// Result on DEBUG
Second argument called with i = 0
First argument called with i = 1
Function called with 1, 0
Second argument called with i = 1
First argument called with i = 2
Function called with 2, 1
Second argument called with i = 2
First argument called with i = 3
Function called with 3, 2
Second argument called with i = 3
First argument called with i = 4
Function called with 4, 3
Second argument called with i = 4
First argument called with i = 5
Function called with 5, 4

如您所见,在这两种情况下,第二个参数都在第一个参数之前求值(如果参数是在某种后进先出堆栈中处理的,那是我所期望的);但在 release 中,变量 i 的增量被“优化掉”并延迟到循环的下一次迭代。这是出乎意料的,我真的很想了解发生了什么。

当然,我可以通过将循环更改为

来轻松“修复”我的代码
    for (int i = 0; i < 5; ++i) function(firstarg(i+1), secondarg(i)); 

无论编译参数如何,它都会给出相同的结果。但是,我仍然很想了解这种增量优化背后的原因。

附言。顺便说一句,我无法在 linux 下使用 gcc 重现这个问题(使用 -O0 标志调试,使用 -O3 发布)。

最佳答案

您误解了结果。增量不会“优化掉”或延迟到循环的下一次迭代。您只是无法在下一次迭代之前查看 i 的值。试试这个:

for (int i = 0; i < 5; )
{
   function(firstarg(i), secondarg(i++)); 
   printf("At end of iteration, i = %d\n");
}

而且您会发现它根本没有延迟。

您的代码是 UB,因为您可以访问变量并修改同一变量而无需中间序列点。虽然您可能会得到非常疯狂的结果,但实际上您会得到两个“预期”结果,具体取决于您的优化。未指定计算函数参数的顺序。

关于c++ - 增量优化掉(Visual C Express 2010),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12245473/

相关文章:

c++ - 在不改变值(value)、性能的情况下多次访问位域?

qt - 如何在Visual C++ 2010中导入QT项目?

c++ - 如何将 "void (MyClass::*)(int)"转换为 "void (*)(int)"?

java - 在 Java 中创建符号表时在编译时考虑未知变量值

c++ - 如何判断 win32 c++ 应用程序在 CTRL-ALT-DEL 后是否失去焦点?

c++ - 编译器优化导致性能下降

c++ - CSmtp 不会发送电子邮件附件。但是没有附件它工作正常。 (c++)

c - 如何解决错误 C2059 : syntax error : '__asm' in Visual C++ 2010 Express

c++ - 为什么 reverse_iterator::base 偏移量?

c++ - 如何让编译器警告这是一个无效的 boolean 值?