以下是代码from this question的略微修改版本:
#pragma warning(default:4716)
int recur(int i)
{
int result;
result = (i>1 ? i - recur(i/2) : 3);
// return intentionally omitted
}
int main()
{
return recur(0);
}
请注意recur()
省略return
,因此其行为未定义。以下是Visual C ++ 10为此代码发出的内容:
316: int main()
317: {
00403940 push ecx
318: return recur(0);
00403941 mov eax,dword ptr [esp]
319: }
00403944 pop ecx
00403945 ret
是的,我知道如果出现未定义的行为,则允许任何内容。但是这段代码完全没有意义,而编译器就是一个程序,所以我不会指望它有无意义的东西。
编译器如何管理完全无意义的代码?
答案 0 :(得分:1)
来自编译器观点return smth;
语句意味着简单的事情:生成一些代码以根据调用约定将结果返回给调用者(对于“C”,x86 / amd64和普通类型通常意味着将smth放到{{ 1}} / eax
注册)。如果你错过rax
,这对编译器来说意味着你不会生成这样的代码(return
)。通常它会导致警告(至少):在返回非void 的函数中没有return语句。但是,如果函数体有mov result, %eax
个部分来代替编译器,那就可能很好了......在那种(罕见的)情况下警告通常被#pragma或相应的命令行选项所抑制。是的,总的来说错过了返回导致UB ......
答案 1 :(得分:1)
由于代码具有未定义的行为,编译器可以完全做任何事情,包括生成无意义的代码。
这里最有可能的是编译器忠实地编译了你的代码并将其传递给优化器,优化器进行了一些内联和常量表达式折叠。
在破坏的代码上使用该过程恰好会导致您看到的内容。