请考虑以下代码:
int fac_aux( int x, int res ) {
if( x == 1 ) return res;
else return fac_aux( x - 1, res * x );
}
int fac( int x ) {
return fac_aux( x, 1 );
}
int main() {
int x = fac( 50 );
std::cout << x;
return 0;
}
根据生成的asm文件,一切正常,尾部调用已优化。
尝试替换
int x = fac( 50 );
与
int x = fac_aux( 50, 1 );
奇怪,但尾调用优化消失了。据我所知,在VS2008中没有这么奇怪的编译器行为。任何有关这些事情发生的想法以及如何确定尾部调用优化都已完成?
函数编译标志:/ Ogtp
尝试了两个/ O2和/ Ox优化标志。是否有其他重要的编译器选项?
编辑:VS2012设法进行优化
答案 0 :(得分:1)
我尝试了以下代码
#include "stdafx.h"
int f( size_t i, int x )
{
return ( ( i < 2 ) ? x : f( i - 1, i * x ) );
}
int f( size_t i )
{
return ( f( i, 1 ) );
}
int _tmain(int argc, _TCHAR* argv[])
{
{
f( 0 );
}
return 0;
}
并使用了完整的优化/ Ox但我没有得到尾递归。所以似乎MS VC ++ 2010不支持尾递归。
答案 1 :(得分:1)
编译原始文件时,调用点上的程序集部分内联fac_aux
,特别是x - 1
部分,这是尾递归所必需的,但使用fac_aux
可以防止部分内联,从而尾递归优化:
TestThin.fac_aux 013B1000 CMP ECX,1
013B1003 JE SHORT TestThin.013B100E
013B1005 IMUL EAX,ECX
013B1008 DEC ECX
013B1009 CMP ECX,1
013B100C JNZ SHORT TestThin.013B1005
013B100E RETN
013B100F INT3
TestThin.main 013B1010 MOV EAX,32
013B1015 LEA ECX,DWORD PTR DS:[EAX-1] ;notice the partial inlining of x - 1
013B1018 CALL TestThin.fac_aux
答案 2 :(得分:0)
尝试明确地使用inline
函数 - 此外,您使用的是什么优化级别?
答案 3 :(得分:0)
我不知道它是否可行,但尝试用单个return语句替换if ... else:
return (x == 1) ? res : fac_aux( x - 1, res * x );
答案 4 :(得分:0)
看起来很奇怪,你在做某种增量编译吗? 除此之外,可能是编译器感到困惑的事实 多个参数,在工作版本中有效 只有一个参数,以某种方式优化不再符合条件。
您可以尝试将res参数设置为全局,我知道它是凌乱的 不好的做法,但它可能会奏效。
听起来像编译器错误/功能。
/托尼