关于c ++:我们可以拥有多少个指针级别?

How many levels of pointers can we have?

一个变量中允许多少个指针(*

让我们考虑下面的例子。

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

同样,我们可以

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

等等。

例如,

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


C标准规定了下限:

5.2.4.1 Translation limits

276 The implementation shall be able to translate and execute at least one program that contains at least one instance of every one of the following limits: [...]

279 — 12 pointer, array, and function declarators (in any combinations) modifying an
arithmetic, structure, union, or void type in a declaration

上限是特定于实现的。


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

当然,无限指针间接是在结构的帮助下实现的,而不是直接声明器,这是不可能的。并且需要一个结构,这样您就可以在该结构中的不同级别包含其他数据,从而终止该结构。

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

现在您可以使用list->next->next->next->...->next。这实际上只是多指针间接寻址:*(*(..(*(*(*list).next).next).next...).next).next。当它是结构的第一个成员时,.next基本上是一个noop,所以我们可以把它想象成***..***ptr

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

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


理论上:

你可以随心所欲地进行多层次的间接审判。

实际上:

当然,没有任何消耗内存的东西是不确定的,因为主机环境上的可用资源会有限制。因此,实际上,对一个实施所能支持的内容有一个最大限度的限制,并且该实施应适当地记录下来。因此,在所有这些工件中,标准没有指定最大限制,但它指定了下限。

参考资料如下:

C99标准5.2.4.1翻译限制:

— 12 pointer, array, and function declarators (in any combinations) modifying an
arithmetic, structure, union, or void type in a declaration.

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

18) Implementations should avoid imposing fixed translation limits whenever possible.


正如人们所说,理论上没有限制。不过,出于兴趣,我用G++4.1.2运行了这个程序,它的大小可以达到20000。编译非常慢,所以我没有尝试更高的编译速度。所以我想G++也没有任何限制。(尝试设置size = 10并查看ptr.cpp,如果它不是立即明显的。)

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

肌酸蛋白磷酸酶

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <iostream>

int main()
{
    const int size = 200;
    std::cout <<"#include <iostream>

"
;
    std::cout <<"int main()
{
"
;
    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 <<";
"
;
    }
    std::cout <<"    std::cout <<";
    for (int i = 1; i < size; ++i) std::cout <<"*";
    std::cout <<"i" << size-1 <<" << "\
";
"
;
    std::cout <<"    return 0;
}
"
;
    return 0;
}


听起来很有趣。

  • 视觉工作室2010(on windows 7),在遇到这个错误之前,你可以有1011个级别:

    fatal error C1026: parser stack overflow, program too complex

  • 没有坠机的话,100K+*!我想硬件是这里的极限。

(仅以一项可变宣言测试)


没有限制,请检查这里的示例。

答案取决于您所说的"指针级别"。如果您所说的"一个声明中可以有多少个间接级别?"答案是"至少12个"。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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 */

如果你的意思是"在程序变得难以读取之前,你可以使用多少级指针",那是一个品味问题,但是有一个限制。有两个间接的层次(指向某物的指针)是常见的。任何超过这一点的事情都会变得更难思考;除非选择的方案更糟,否则不要这样做。

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


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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <cstdio>

typedef void (*FuncType)();

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

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

如图所示,这给出了:

Hello, World!
Hello, World!
Hello, World!

而且它不涉及任何运行时开销,所以您可以根据需要将它们堆叠起来…直到编译器在文件上阻塞。


没有界限。一个指针是一个记忆中的一个错误,它的内容是一个地址。如你所说

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

指针是另一指针的地址的变量。

ZZU1

这里是指针指针控制器的地址是p,该地址已准备好控制器的地址是a

指针对指针没有特别的意义。因此,在小马链上没有任何限制,而小马链上有另一个指针的地址。他

1
 int **************************************************************************z;

这是允许的。


注意,这里有两个可能的问题:在C类型中,我们可以实现多少级的指针间接寻址,以及我们可以将多少级的指针间接寻址填充到一个声明符中。

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

1
2
3
typedef int *type0;
typedef type0 *type1;
typedef type1 *type2; /* etc */

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


每个C++++++开发者都应该听得到三个著名的星程序员

看上去有点神奇的"指针屏障"需要伪装

BLCK1/


我想说的是,制作一个任意数*的人,是一个可以用模板编程的人。我忘了我做的是什么,但它建议我可以生产一些新的不同类型的金属,用T*类型。

温度偏编程是一个缓慢的下降到疯狂,所以当产生一种具有几种间接离子水平的类型时,不需要道歉。这只是一种绘制Peano Integers地图的方法,比如说,以功能语言的形式缓慢扩张。


Rule 17.5 of the 2004 MISRA C Standard Prohibits more than 2 levels of pointer direction.


没有什么比实际限制更重要的了所有指针都是变量,通常存储在堆栈不加热。堆栈通常很小(在某些链接中,堆栈的尺寸可能改变)。所以说你有4MB堆栈,什么是正常尺寸。并让我们说,我们有4个字节大小的指针(指针大小与建筑、目标和编译设置不同)。

在本案中,可能的最大数目是10548576,但我们不应忽视其他一些工作人员的事实。

然而,有些编译器可能有最大的指针链,但极限是大小。所以,如果你在无限连接中增加堆栈的尺寸,并拥有无限记忆的机器,它运行的是无限记忆的手柄,所以你将拥有无限的指针链。

如果你使用int *ptr = new int;,并将指针放到热中,这不是很常见的限制尺寸,而不是堆栈。

版权声明:转载时请以超链接形式标明文章原始出处。如果机器有更多的记忆,指针的尺寸就会增加。如果记忆是无限的,指针的大小是无限的,那么这是坏消息。注:


这取决于你的店铺指针的位置。如果他们在堆栈里,你就离开了低极限。如果你把它放在头顶上,你的限制是非常高的。

Look at this program:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#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;
}

它创造了1米的指针,并展示了什么是方便地知道链条向第一个变量EDOCX1〕〔7〕

所以想象一下你能走多远。