尾部调用优化对返回void的函数的递归调用有效吗?例如,我有一个函数,void fun()
void fun()
{
...
...
...
fun();
}
在这里,编译器不会知道,调用fun()是最后一条语句。那么尾部调用优化是否只针对返回某些值的函数?
答案是可以,但编译器没有义务这么做。这在很大程度上取决于函数、编译器和所选的优化级别。如果您关心某个特定函数的这一点,请查看特定编译器在特定优化级别生成的程序集。
更具体地说,GCC(至少是使用LLVM作为后端的苹果版本)将为至少一些返回优化级别-O1
或更好的空
的函数生成尾部调用优化代码。
一些测试代码:
/* Fills an array with a single value, recursively with side effects */
void fillarray(int val, int* curr, int* end)
{
if (curr==end) return;
*curr = val;
fillarray(val,curr+1,end);
}
通过最少的优化(-O1
),编译到汇编(gcc-O1-S test.c
)会产生一个很好的尾部调用优化函数:
_fillarray:
pushq %rbp
movq %rsp, %rbp # set up the stack
cmpq %rdx, %rsi # early exit if beg == end
je LBB1_2
LBB1_1:
movl %edi, (%rsi) # *curr = val
addq $4, %rsi # curr++
cmpq %rsi, %rdx # TAIL CALL optimization is here
jne LBB1_1 # if curr != end, go to LBB1_1
LBB1_2:
popq %rbp # restore the stack and exit
ret
(注意:我已经编辑掉了一些不必要的标签和对齐语句,它们模糊了组件的结构)。
此外,当优化关闭时(-O0
),生成的代码是递归的(不是尾部调用优化)。
我正在学习指针是如何工作的,但我不明白这段代码中的一件事。在void*函数中返回int就像一个咒语,但是返回float就不是了。
我找到了一些很好的SO链接(如何从异步回调函数返回值?以及从node.js中的回调函数返回值等),但它们并不是不能为我的问题提供解决方案。 我的问题:能够得到异步调用的结果,但我如何使用这个结果返回我的函数? 这里获取callBackResponse的值为true或false,并希望将该值用作:
问题内容: 我正在使用Postgresql 8.3,并具有以下简单功能,该功能会将a返回 给客户端 现在,我可以使用以下SQL命令来调用此函数并操纵返回的游标,但是游标名称是由PostgreSQL自动生成的 此外,如38.7.3.5中所述,显式地将游标名称声明为函数的输入参数 。返回游标。我可以声明自己的游标名称并使用此游标名称来操纵返回的游标,而不是为我自动生成的Postgresql吗?如果不是
在C 11中,如何专门化一个函数模板,该模板使用decltype声明为“复杂”的尾部返回类型?以下内容适用于GCC,但在VC2013中产生了“错误C2912:显式专业化‘int f(void)’i不是功能模板的专业化”: 我说“复杂”是因为缺乏一个技术上精确的词,因为我不确定是什么造成了差异。例如,以下decltype使用不依赖于任何函数结果类型的内置操作,可以与模板专业化配合使用: 自动f()-
C和C中有没有办法让返回void的函数按照未指定的顺序求值? 我知道函数参数是按未指定的顺序计算的,因此对于不返回void的函数,这可用于以未指定的顺序计算这些函数: 合格编译器编译的合法C和C代码可以按任何顺序打印< code>hi 、< code>bye和< code>moo。这并不是未定义的行为(鼻魔是无效的),有效的输出不止一个,但不一定是无限的,一个兼容的编译器甚至不需要确定它产生了什么
我正在编写自己的编程语言,由于各种原因,它编译为C。(其中之一是我对汇编知之甚少)。 我有一个关于编译器(例如GCC或Clang)如何优化从函数返回值的问题。假设我有这样的代码: 我的理解是,您可能希望变量A在从FUNC返回时复制到B(如果A和B是结构,这可能会很昂贵)。编译器会认识到在这种情况下,B可以指向a所在的位置,而不需要拷贝吗? 如果main()看起来像这样:怎么办? 谢谢大家!