我们在 C 中可以拥有的指向指针的指针数量的限制是多少?

pas*_*ure 8 c pointers limit language-lawyer

在 C 中,我知道我们可以用指针来做到这一点:

int *p;          /* an int pointer (ptr to an int) */
int **pp;        /* a pointer to an int pointer (ptr to a ptr to an int) */
Run Code Online (Sandbox Code Playgroud)

乃至:

int **app[];            /* an array of pointers to int pointers */
int (**ppa)[];          /* a pointer to a pointer to an array of ints */
int (**ppf)();          /* a pointer to a pointer to a function returning an int */
int *(*pap)[];          /* a pointer to an array of int pointers */
int **fpp();            /* a function returning a pointer to an int pointer */
Run Code Online (Sandbox Code Playgroud)

但是我们可以做一些像无限的三个指针吗?例如:

int ***ppp;             /* a pointer to a pointer to an int pointer */
int ****pppp;           /* a pointer to a pointer to a pointer to an int pointer */
Run Code Online (Sandbox Code Playgroud)

...依此类推,直到无穷大。

我们可以拥有的指向指针的指针数量有上限吗?如果是,上限是多少?

klu*_*utt 11

该标准没有规定任何上限。它所说的是编译器至少需要支持12 个。

在实际代码中,它可以被认为是无限的。只有当您编写的程序编写的程序是人类不应阅读的程序时,这才有意义。大多数程序员会说你应该用三颗星作为警告。没有很好的理由不要超过两个。

我在 gcc 上尝试了 10000 并且它起作用了。我现在正在尝试 100000。一件有趣的事情是编译需要很长时间。编译花了几分钟,唯一的语句是一个带有 10000 颗星的指针声明。

生成C文件的代码:

// gen.c
#include <stdio.h>

int main()
{
    const size_t n = 10000;
    printf("int main(){int ");
    for(size_t i=0; i<n; i++)
        printf("*");
    printf("p;}\n");
}
Run Code Online (Sandbox Code Playgroud)

跑:

$ gcc gen.c -c gen
$ ./gen > stars.c
$ gcc stars.c
Run Code Online (Sandbox Code Playgroud)

回复评论:

这是一个有趣的实验,但我不会进一步研究。


And*_*nle 11

C 11 标准没有强加最大限制,实际上声明“实现应尽可能避免强加固定的翻译限制。” 在脚注中

最低限值由5.2.4 环境限值给出:

实现应能够翻译和执行至少一个程序,该程序包含以下每一项限制的至少一个实例:18)

  • 127 层嵌套块
  • 63 个嵌套级别的条件包含
  • 12 个指针、数组和函数声明符(任意组合)修改声明中的算术、结构、联合或 void 类型
  • 一个完整的声明符中有 63 个嵌套级别的括号声明符
  • 完整表达式中有 63 个嵌套级别的括号表达式
  • 内部标识符或宏名称中的 63 个有效初始字符(每个通用字符名称或扩展源字符被视为单个字符)
  • 外部标识符中的 31 个有效起始字符(每个指定短标识符为 0000FFFF 或更少的通用字符名称被视为 6 个字符,每个指定短标识符为 00010000 或更多的通用字符名称被视为 10 个字符,每个扩展源字符被视为与相应的通用字符名称相同的字符数(如果有)
  • 一个翻译单元中有 4095 个外部标识符
  • 在一个块中声明了 511 个具有块作用域的标识符
  • 在一个预处理翻译单元中同时定义了 4095 个宏标识符
  • 一个函数定义中包含 127 个参数
  • 一个函数调用中有 127 个参数
  • 一个宏定义中包含 127 个参数
  • 一个宏调用中有 127 个参数
  • 逻辑源代码行中的 4095 个字符
  • 字符串文字中的 4095 个字符(连接后)
  • 对象中的 65535 字节(仅在托管环境中)
  • #included 文件的 15 个嵌套级别
  • switch 语句的 1023 个 case 标签(不包括任何嵌套 switch 语句的标签)
  • 单个结构或联合中的 1023 个成员
  • 单个枚举中的 1023 个枚举常量
  • 单个结构声明列表中的 63 级嵌套结构或联合定义

符合标准的 C 编译器将提供至少 12 级指针间接。