指针可以有多少层?

在一个变量中允许有多少个指针(*) ?

让我们考虑下面的例子。

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

类似地,我们可以有

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

等等。

例如,

int ****************zz;
53037 次浏览

从理论上讲:

你可以有任意多的间接层次。

实际:

当然,任何消耗内存的操作都不能是无限的,主机环境中的可用资源会有限制。因此,实际上实现所能支持的内容是有最大限制的,实现应该适当地记录它。因此,在所有这些工件中,标准没有指定最大限度,但它指定了下限。

参考资料如下:

5.2.4.1翻译限制:

- 12指针、数组和函数声明符(任何组合) 声明中的算术、结构、联合或空类型

这指定了每个实现必须支持的下限。注意,在一个脚注中,标准进一步说:

18)实现应该尽可能避免强加固定的翻译限制。

没有限制,检查例子C面试问题和答案

答案取决于你对“指针的级别”的定义。如果你的意思是“在一份声明中你可以有多少层间接?”答案是“至少12个”。

int i = 0;


int *ip01 = & i;


int **ip02 = & ip01;


int ***ip03 = & ip02;


int ****ip04 = & ip03;


int *****ip05 = & ip04;


int ******ip06 = & ip05;


int *******ip07 = & ip06;


int ********ip08 = & ip07;


int *********ip09 = & ip08;


int **********ip10 = & ip09;


int ***********ip11 = & ip10;


int ************ip12 = & ip11;


************ip12 = 1; /* i = 1 */

如果你的意思是“在程序变得难以阅读之前,你可以使用多少级指针”;这是个人喜好的问题,但也有限度。有两层间接(一个指针指向另一个指向某物的指针)是很常见的。再多一点就很难想象了;除非另一种选择会更糟,否则不要做。

如果你的意思是“你在运行时可以有多少层指针间接”,没有限制。这一点对于循环列表尤其重要,因为循环列表中的每个节点都指向下一个节点。您的程序可以永远跟随指针。

C标准指定了下限:

5.2.4.1翻译限制

实现应能够翻译和执行至少一个包含以下每个限制的至少一个实例的程序:[…]

< p > 279本;12指针、数组和函数声明符(任意组合)修改 声明中的算术、结构、联合或空类型

上限是特定于实现的。

正如人们所说,“理论上”没有限制。然而,出于兴趣,我用g++ 4.1.2运行了这个程序,它可以在大小为20,000的情况下工作。编译非常慢,所以我没有尝试更高的编译。所以我猜g++也没有施加任何限制。(尝试设置size = 10并在ptr.cpp中查找,如果不是立即明显的话。)

g++ create.cpp -o create ; ./create > ptr.cpp ; g++ ptr.cpp -o ptr ; ./ptr

create.cpp

#include <iostream>


int main()
{
const int size = 200;
std::cout << "#include <iostream>\n\n";
std::cout << "int main()\n{\n";
std::cout << "    int i0 = " << size << ";";
for (int i = 1; i < size; ++i)
{
std::cout << "    int ";
for (int j = 0; j < i; ++j) std::cout << "*";
std::cout << " i" << i << " = &i" << i-1 << ";\n";
}
std::cout << "    std::cout << ";
for (int i = 1; i < size; ++i) std::cout << "*";
std::cout << "i" << size-1 << " << \"\\n\";\n";
std::cout << "    return 0;\n}\n";
return 0;
}

请注意,这里可能存在两个问题:在C类型中可以实现多少层指针间接,以及在单个声明器中可以填充多少层指针间接。

C标准允许对前者施加一个最大值(并给出一个最小值)。但这可以通过多个typedef声明来避免:

typedef int *type0;
typedef type0 *type1;
typedef type1 *type2; /* etc */

因此,最终,这是一个实现问题,与C程序在被拒绝之前可以做出多大/多复杂的想法有关,这是非常特定于编译器的。

实际上,使用指向函数的指针更有趣。

#include <cstdio>


typedef void (*FuncType)();


static void Print() { std::printf("%s", "Hello, World!\n"); }


int main() {
FuncType const ft = &Print;
ft();
(*ft)();
(**ft)();
/* ... */
}

在这里所示,这给出:

< p >你好,世界!< br > 你好,世界!< br > 你好,世界!< / p >

而且它不涉及任何运行时开销,所以你可以尽可能多地堆叠它们……直到编译器被文件阻塞。

实际上,C程序通常使用无限指针间接。一个或两个静态级别是常见的。三重间接是很少见的。但是无限是很常见的。

无限指针间接是在结构的帮助下实现的,当然,不是通过直接的声明器,这是不可能的。需要一个结构体,这样你就可以在不同的层次上在这个结构中包含其他数据。

struct list { struct list *next; ... };

现在你可以拥有list->next->next->next->...->next。这实际上就是指向的多个指针:*(*(..(*(*(*list).next).next).next...).next).next。当.next是结构的第一个成员时,它基本上是一个noop,所以我们可以把它想象成***..***ptr

这实际上没有任何限制,因为链接可以通过循环来遍历,而不是像这样一个巨大的表达式,而且,结构可以很容易地变成圆形。

因此,换句话说,链表可能是添加另一层间接来解决问题的最终示例,因为您对每个推操作都是动态地进行操作的。:)

听起来很有趣。

  • Visual Studio 2010(在Windows 7上),在得到这个错误之前,你可以有1011个级别:

    解析器堆栈溢出,程序太复杂

    李< /引用> < / >
  • gcc (Ubuntu), 100k+ *没有崩溃!我想硬件是这里的极限。

(仅用变量声明进行测试)

没有限制。指针是一个内存块,其内容是一个地址。< br > 如你所说

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

指向指针的指针也是一个变量,它包含另一个指针的地址。< br >

int **q = &p;

这里q是指向指针的指针,指针保存了p的地址,而p已经保存了a的地址。

指针指向指针没有什么特别的。
因此,存储另一个指针地址的浮点数链没有限制 ie . < / p >
 int **************************************************************************z;

是被允许的。

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

每个c++开发人员都应该听说过著名的三星程序员

而且似乎真的有某种神奇的“指针障碍”。这需要伪装。

C2引用:

三星程序员

c语言程序员的评分系统。你的指针越间接(即越多"*"在变量之前),你的声誉就会越高。几乎不存在无星c程序员,因为几乎所有重要的程序都需要使用指针。大多数程序员都是一星程序员。在过去(好吧,我还年轻,所以至少对我来说这看起来像过去),人们偶尔会发现一段由三星程序员编写的代码,并因敬畏而颤抖。 有些人甚至声称他们看到过包含函数指针的三星代码,而且是在不止一个间接层次上。

没有像真正的限制这样的东西,但是limit存在。所有指针都是通常存储在堆栈不是堆中的变量。堆栈通常很小(在一些链接过程中可以改变它的大小)。假设你有4MB的堆栈,这是很正常的大小。假设我们有一个4字节大小的指针(指针大小取决于架构、目标和编译器设置)。

在本例中4 MB / 4 b = 1024,因此可能的最大数字将是1048576,但我们不应该忽略堆栈中还有其他东西的事实。

然而,一些编译器可能有最大数量的指针链,但限制是堆栈大小。因此,如果你在链接过程中增加堆栈大小,让机器拥有无限大的内存,运行操作系统来处理这些内存,那么你就会有无限的指针链。

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

只要意识到infinity / 2 = infinity。如果机器有更多的内存,那么指针的大小就会增加。如果内存是无穷大,指针的大小也是无穷大,这是个坏消息。:)

这取决于你存储指针的位置。如果它们在堆栈中,则有很低限制。如果你把它存储在堆里,你的极限会非常非常高。

看看这个程序:

#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

顺便说一句。它使用RAM的92K,所以想象一下你能走多深。

我想指出的是,生成带有任意数量*的类型是可以通过模板元编程实现的。我忘了我到底在做什么,但有人建议我可以通过使用递归 T*类型来生成新的不同类型,这些类型之间具有某种元操作。

模板元编程是一个慢慢陷入疯狂的过程,所以在生成一个有几千个间接层的类型时,没有必要找借口。例如,它只是将peano整数作为函数式语言映射到模板展开的一种方便方法。