为什么功能中的本地阵列似乎可以防止TCO
Why local arrays in functions seem to prevent TCO?
看起来函数中有一个本地数组会阻止我检查过的所有编译器对其进行尾调用优化:
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
实现了预期的TCO。
本地数组中是否存在无法优化尾部调用的内容?
如果编译器执行TCO,那么所有外部foo(arr)
调用都将接收到相同的指针。这是一个可见的语义变化,因此不再是纯粹的优化。
有问题的局部变量是一个数组,这可能是转移注意力;重要的是它通过指针对外部的可见性。
考虑一下这个程序:
#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) = %dn", tail_function(0));
return 0;
}
当tail_function
通过尾部调用进行递归时,record
函数会记录局部变量x
的不同实例的地址。当它的空间用完时,它返回1
,从而触发tail_function
调用tally
并返回。CCD_ 11扫描记录的存储器位置并将它们的值相加。
如果tally
受制于TCO,则只有一个x
的实例。实际上,它是这样的:
int tail_function(int x)
{
tail:
if (record(&x))
return tally();
x = x + 1;
goto tail;
}
因此,现在,record
一遍又一遍地记录相同的位置,导致tally
计算的值不正确,而不是预期的21
。
record
和tally
的逻辑取决于每次激活作用域时实际实例化的x
,并且作用域的外部激活具有持续到内部激活终止的寿命。该要求排除了tail_function
在恒定空间中的递归;它必须分配单独的CCD_ 21实例。
相关文章:
- OpenMP阵列性能较差
- 如何将三维尺寸不固定的三维阵列展平为一维阵列
- 当我的阵列太大时出现分段错误
- 位阵列上的快速AND运算
- 阵列必须使用大括号封闭的初始器进行初始化
- 没有从阵列<float>到阵列<int>的可行转换
- C++动态安全 2D 交错阵列
- 将平面阵列重塑为复杂的特征类型
- 如何使用英特尔 PIN 捕获阵列的所有负载?
- 为什么我能够为阵列分配比计算机实际拥有的内存更多的内存
- 库特<<恩德尔;不适用于打印 2D 阵列
- 数组类 阵列的打印输出
- 从较小的阵列到较大的阵列的元素级转换
- 仅在大型阵列上出现合并排序分段错误
- 从阵列C++中删除重复项
- 阵列的大小在C++中是否灵活?
- 反转阵列中的正序列
- 具有可变尺寸的 C++ 2D 阵列
- 二维阵列的动态分配
- 为什么功能中的本地阵列似乎可以防止TCO