在使用 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
如您所见,在这两种情况下,第二个参数都在第一个参数之前进行评估(如果参数是在某种 LIFO 堆栈中处理的,那是我所期望的);但是在 release 中,变量 i 的增量被“优化掉”并延迟到循环的下一次迭代。这是出乎意料的,我真的很想了解发生了什么。
当然,我可以通过将循环更改为轻松“修复”我的代码
for (int i = 0; i < 5; ++i) function(firstarg(i+1), secondarg(i));
无论编译参数如何,它都会给出相同的结果。但是,我仍然很想了解这种增量优化背后的原因。
PS。顺便说一句,我无法在 linux 下使用 gcc 重现此问题(使用 -O0 标志进行调试,使用 -O3 进行发布)。