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

让我们考虑下面的例子。

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

类似地,我们可以有

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

等等。

例如,

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

当前回答

请注意,这里可能存在两个问题:在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)();
  /* ... */
}

如下图所示:

你好,世界! 你好,世界! 你好,世界!

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

没有限制,查看例子在指针::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 */

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

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

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

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

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

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

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

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

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

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

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