我知道我可以使用选项
-fno-optimize-sibling-calls
在 GCC 中禁用尾递归优化。但是,它禁用了整个编译单元的优化。
有没有办法禁用单个功能的优化?
据我所知,我可以更改函数,使其不是尾递归的有效候选者 - 例如,通过在表达式中使用返回值,因此返回不是函数中的最后一条指令。例如:
return f(n) + 1;
上面的解决方案可能仍然是可优化的,并且编译器的未来(或当前,我不知道)版本可能足够聪明,可以将其变成尾调用 - 比如说,通过改变
int f(i) {
if(!i) return 0;
return f(i - 1) + 1;
}
进入
int f(i, r = 0) {
if(!i) return r;
return f(i - 1, r + 1);
}
我正在寻找一种更简洁、面向未来的解决方案,如果可能的话,它不需要更改算法。
查看文档我找不到函数属性或内置函数,但我的搜索并不详尽。
您可以使用特定于 GCC 的
#pragma optimize()
指令(结合适当的括号与推送/弹出 #pragma
行)来实现类似于指定函数属性的结果:
#pragma GCC push_options // Save current options
#pragma GCC optimize ("no-optimize-sibling-calls")
int test(int i)
{
if (i == 1) return 0;
return i + test(i - 1);
}
#pragma GCC pop_options // Restore saved options
int main()
{
int i = 5;
int j = test(i);
return j;
}
但请注意,clang 不支持这种形式的
#pragma optimize
。另外,请注意手册中的警告:
不是每个以指定的 -f 前缀开头的优化选项 属性必然会对功能产生影响。这 optimize 属性应该仅用于调试目的。这是 不适合生产代码。
__attribute__((__optimize__("no-optimize-sibling-calls")))
似乎适用于 GCC。
Clang 给
warning: unknown attribute '__optimize__' ignored
.