为什么这个尾部调用递归斐波那契函数会与gcc-O2相冲突?

为什么这个尾部调用递归斐波那契函数会与gcc-O2相冲突?,c,gcc,recursion,fibonacci,tail-recursion,C,Gcc,Recursion,Fibonacci,Tail Recursion,我实现了以下尾部调用递归fibonacci函数来尝试gcc的尾部调用优化(): 我注意到,对于-O2,它似乎完成了TCO(注意上面的一行:jmp fib_helper.1752)。但是,这是始终返回0的非工作版本 然后,我使用-O1生成程序集来检查差异(gcc-O1-std=gnu99-S fib_tc.c-o fib_tc1.S): 这个版本(有效)似乎没有经过尾部调用优化(基于上面对fib_helper的调用) 如上所示,我在Fedora20Linux(64位)上使用GCC4.8.2 在我断

我实现了以下尾部调用递归fibonacci函数来尝试gcc的尾部调用优化():

我注意到,对于-O2,它似乎完成了TCO(注意上面的一行:jmp fib_helper.1752)。但是,这是始终返回0的非工作版本

然后,我使用-O1生成程序集来检查差异(gcc-O1-std=gnu99-S fib_tc.c-o fib_tc1.S):

这个版本(有效)似乎没有经过尾部调用优化(基于上面对fib_helper的调用)

如上所示,我在Fedora20Linux(64位)上使用GCC4.8.2

在我断定gcc中存在与TCO相关的bug之前,我想检查一下,以确保我在代码或分析中没有做错什么

编辑:正如注释中指出的,嵌套函数可能存在问题,我也尝试使用单独的函数,如下所示,并且始终返回0:

uint64_t fib_helper(uint8_t n, uint64_t acc, uint64_t prev) {
  if(n == 0) 
    return acc;
  else
    return fib_helper( n-1, acc+prev, acc);
}

uint64_t fib_tc( uint8_t n) {
  fib_helper(n,1,0);
}
EDIT2:正如下面的评论所指出的,我错过了回报(我想我最近做了太多的OCaml:)应该是:

uint64_t fib_tc( uint8_t n) {
  uint64_t fib_helper(uint8_t n, uint64_t acc, uint64_t prev) {
    if(n == 0) 
      return acc;
    else
      return fib_helper( n-1, acc+prev, acc);
  }
  return fib_helper(n,1,0);
}

嵌套函数是一种大规模的攻击。请不要使用它们。@sharth:我也尝试过同样的代码,但结果是一样的。打字错误<代码>fib_-helper(n,1,0)->
返回fib\u helper(n,1,0)。。。使用
-Wall
将代码标记为警告。似乎只是您忘记了返回值!我很惊讶它被编译了。这只是未定义的行为,从返回值函数的末尾掉下来是未定义的,请参阅。
    .file   "fib_tc.c"
    .text
    .type   fib_helper.1752, @function
fib_helper.1752:
.LFB1:
    .cfi_startproc
    movq    %rsi, %rax
    testb   %dil, %dil
    je  .L6
    subq    $8, %rsp
    .cfi_def_cfa_offset 16
    leaq    (%rsi,%rdx), %rax
    subl    $1, %edi
    movzbl  %dil, %edi
    movq    %rsi, %rdx
    movq    %rax, %rsi
    call    fib_helper.1752
    addq    $8, %rsp
    .cfi_def_cfa_offset 8
.L6:
    rep ret
    .cfi_endproc
.LFE1:
    .size   fib_helper.1752, .-fib_helper.1752
    .globl  fib_tc
    .type   fib_tc, @function
fib_tc:
.LFB0:
    .cfi_startproc
    subq    $8, %rsp
    .cfi_def_cfa_offset 16
    movzbl  %dil, %edi
    movl    $0, %edx
    movl    $1, %esi
    call    fib_helper.1752
    addq    $8, %rsp
    .cfi_def_cfa_offset 8
   ret
   .cfi_endproc
.LFE0:
    .size   fib_tc, .-fib_tc
    .ident  "GCC: (GNU) 4.8.2 20131212 (Red Hat 4.8.2-7)"
   .section .note.GNU-stack,"",@progbits
uint64_t fib_helper(uint8_t n, uint64_t acc, uint64_t prev) {
  if(n == 0) 
    return acc;
  else
    return fib_helper( n-1, acc+prev, acc);
}

uint64_t fib_tc( uint8_t n) {
  fib_helper(n,1,0);
}
uint64_t fib_tc( uint8_t n) {
  uint64_t fib_helper(uint8_t n, uint64_t acc, uint64_t prev) {
    if(n == 0) 
      return acc;
    else
      return fib_helper( n-1, acc+prev, acc);
  }
  return fib_helper(n,1,0);
}