我们可以有多少级指针?

474

在一个单一变量中可以有多少个指针 (*)?

让我们考虑以下示例。

int a = 10;
int *p = &a;

同样地,我们也可以有

int **q = &p;
int ***r = &q;

等等。

例如,

int ****************zz;

618
如果那成为你真正面临的问题,那么你正在做某件非常错误的事情。 - ThiefMaster
297
你可以不断添加指针级别,直到你的大脑爆炸或编译器崩溃——以先发生的为准。 - JeremyP
54
因为指向指针的指针本质上只是一个指针,所以理论上没有任何限制。也许编译器在超过某个非常高的限制后无法处理它,但是... - Christian Rau
79
使用最新的C++,应该使用类似于 std::shared_ptr<shared_ptr<shared_ptr<...shared_ptr<int>...>>> 这样的东西。 - josefx
52
@josefx - 这显示了C++标准的一个问题 - 没有办法将智能指针提升到幂。我们必须立即要求扩展以支持例如 (pow (std::shared_ptr, -0.3))<T> x; 的-0.3间接层级。 - user180247
显示剩余13条评论
14个回答

6
我想指出,使用模板元编程生成带有任意数量 '*' 的类型是可能发生的事情。我忘记当时具体在做什么,但建议我可以通过使用递归的T*类型产生新的不同类型,并在它们之间进行某种元操作。
模板元编程是一种缓慢陷入疯狂的过程,因此在生成具有数千级间接引用的类型时无需道歉。这只是将Peano整数(例如)映射到模板展开作为函数式语言的便捷方式。

4

2004年的MISRA C标准中的规则17.5禁止超过2个指针间接层级。


17
很确定这是针对程序员的建议,而不是编译器。 - Cole Tobin
3
我阅读了关于指针多次间接引用的规则17.5的文件。它并不一定禁止超过2个级别的指针间接引用。该规则指出,应当遵循此项规定,因为超过2个级别是与其标准不符的。他们规定中的重要词语是使用“should”,来自以下陈述:Use of more than 2 levels of indirection can seriously impair the ability to understand the behavior of the code, and should therefore be avoided. 这些是该组织设定的指南,而非语言标准所设定的规则。 - Francis Cugler

-1

不存在所谓的真正的限制,但是确实存在限制。所有指针都是变量,通常存储在堆栈而不是堆中。堆栈通常很小(在某些链接期间可以更改其大小)。因此,假设您有4MB的堆栈,这是相当正常的大小。假设我们有一个指针,它的大小为4个字节(指针大小取决于架构、目标和编译器设置而不同)。

在这种情况下,4 MB / 4 b = 1024,因此可能的最大数量将是1048576,但我们不应忽略堆栈中的其他一些内容。

然而,一些编译器可能具有指针链的最大数量,但限制是堆栈大小。因此,如果您在链接期间将堆栈大小增加到无限,并且拥有运行处理该内存的操作系统的内存无限的机器,则将拥有无限的指针链。

如果您使用int *ptr = new int;并将指针放入堆中,则不是那么通常的方式,限制将是堆大小,而不是堆栈。

编辑 刚刚意识到 infinity / 2 = infinity。如果机器有更多的内存,指针大小会增加。因此,如果内存是无限的,指针大小也是无限的,那么这是一个坏消息... :)


4
A) 指针可以存储在堆上(new int*)。 B) 一个 int* 和一个 int********** 在合理的架构中大小相同。 - user142019
@rightfold A) 是的,指针可以存储在堆中。但是,这将是一件非常不同的事情,就像创建一个容器来保存指向下一个前一个指针的指针一样。B) 当然,int*int**********具有相同的大小,我并没有说它们不同。 - ST3
2
那么我不明白栈大小如何有任何关联。 - user142019
@rightfold 我一直在思考数据分配的“通常”方式,即所有数据都在堆中,而在栈中只是指向该数据的指针。这可能是“通常”的方式,但我同意在栈中放置指针也是可行的。 - ST3
当然,int* 和 int********** 的大小是相同的 - 标准并不保证这一点(尽管我不知道任何平台不符合这个规则)。 - Martin Bonner supports Monica

-3

这取决于您存储指针的位置。如果它们在堆栈中,您的限制相当低。如果您将其存储在堆中,则限制要高得多。

看看这个程序:

#include <iostream>

const int CBlockSize = 1048576;

int main() 
{
    int number = 0;
    int** ptr = new int*[CBlockSize];

    ptr[0] = &number;

    for (int i = 1; i < CBlockSize; ++i)
        ptr[i] = reinterpret_cast<int *> (&ptr[i - 1]);

    for (int i = CBlockSize-1; i >= 0; --i)
        std::cout << i << " " << (int)ptr[i] << "->" << *ptr[i] << std::endl;

    return 0;
}

它创建了1M个指针,并显示了每个指针指向的内容,很容易注意到链条指向第一个变量number

顺便说一下,它使用了92K的RAM,所以想象一下你可以深入多少。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接