首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么函数中的本地数组似乎会阻止TCO?

为什么函数中的本地数组似乎会阻止TCO?
EN

Stack Overflow用户
提问于 2016-08-11 00:16:21
回答 1查看 151关注 0票数 4

看起来在你的函数中有一个局部数组阻止了在我检查过的所有编译器上的尾部调用优化:

代码语言:javascript
复制
int foo(int*);

int tco_test() {
    // int arr[5]={1, 2, 3, 4, 5}; // <-- variant 1
    // int* arr = new int[5]; // <-- variant 2
    int x = foo(arr);
    return x > 0 ? tco_test() : x;
}

variant 1处于活动状态时,最终会真正调用tco_test() (之前,gcc试图进行一些展开操作,但最终仍会调用该函数)。Variant 2的总拥有成本与预期不谋而合。

是不是局部数组中的某些东西使得优化尾部调用变得不可能?

EN

回答 1

Stack Overflow用户

发布于 2016-08-11 00:43:09

如果编译器执行了TCO,那么所有的外部foo(arr)调用都会收到相同的指针。这是一个明显的语义变化,因此不再是纯粹的优化。

有问题的局部变量是一个数组的事实在这里可能是转移注意力;重要的是它通过指针对外部的可见性。

考虑这个程序:

代码语言:javascript
复制
#include <stdio.h>

int *valptr[7], **curptr = valptr, **endptr = valptr + 7;

void reset(void)
{
  curptr = valptr;

}

int record(int *ptr)
{
  if (curptr >= endptr)
    return 1;
  *curptr++ = ptr;
  return 0;
}

int tally(void)
{
  int **pp;
  int count = 0;

  for (pp = valptr; pp < curptr; pp++)
    count += **pp;

  return count;
}

int tail_function(int x)
{
  return record(&x) ? tally() : tail_function(x + 1);
}

int main(void)
{
  printf("tail_function(0) = %d\n", tail_function(0));
  return 0;
}

tail_function递归时,record函数记录局部变量x的不同实例的地址。当空间耗尽时,它返回1,这会触发tail_function调用tally并返回。tally扫描记录的内存位置并将它们的值相加。

如果tally受到总拥有成本的限制,那么将只有一个x实例。实际上,它是这样的:

代码语言:javascript
复制
int tail_function(int x)
{
tail:
  if (record(&x))
    return tally();
  x = x + 1;
  goto tail;
}

因此,现在,record一次又一次地记录相同的位置,导致tally计算出错误的值,而不是预期的21

recordtally的逻辑依赖于x在每次激活作用域时被实例化,并且作用域的外部激活具有持续到内部激活终止的生命周期。这一要求阻止了tail_function在恒定空间中递归;它必须分配单独的x实例。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38878700

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档