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

让我们考虑下面的例子。

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

类似地,我们可以有

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

等等。

例如,

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

当前回答

听起来很有趣。

Visual Studio 2010(在Windows 7上),在得到这个错误之前,你可以有1011个级别: 解析器堆栈溢出,程序太复杂 gcc (Ubuntu), 100k+ *没有崩溃!我想硬件是这里的极限。

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

其他回答

从理论上讲:

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

实际:

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

参考资料如下:

5.2.4.1翻译限制:

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

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

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

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

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

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

如果你使用int *ptr = new int;把指针放到堆里,这不是常用的方法限制的是堆大小,不是堆栈大小。

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

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

g++ create.cpp -o create ; ./create > ptr.cpp ;G++ PTR.cpp -optr ; ./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;
}

这取决于你存储指针的位置。如果它们是堆叠的,极限就会很低。如果你把它存储在堆里,你的极限会非常非常高。

看看这个程序:

#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个指针,并在显示什么指向什么时很容易注意到链到第一个变量数。

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

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

#include <cstdio>

typedef void (*FuncType)();

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

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

如下图所示:

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

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