在一个单一变量中可以有多少个指针 (*
)?
让我们考虑以下示例。
int a = 10;
int *p = &a;
同样地,我们也可以有
int **q = &p;
int ***r = &q;
等等。
例如,
int ****************zz;
在一个单一变量中可以有多少个指针 (*
)?
让我们考虑以下示例。
int a = 10;
int *p = &a;
同样地,我们也可以有
int **q = &p;
int ***r = &q;
等等。
例如,
int ****************zz;
C
标准规定下限:
###5.2.4.1 翻译限制
276 实现应该能够翻译并执行至少包含以下每个限制中至少一个实例的程序:[...]
279 — 在任何组合中修改算术、结构、联合或void类型的12个指针、数组和函数声明符的声明
上限由具体实现决定。
typedef
实现的间接性达到的上限施加限制。 - Kaz实际上,C程序通常利用无限指针间接引用。一到两个静态级别很常见,三重间接引用则很少见。但是无限引用却非常普遍。
当然,无限指针间接引用是通过结构体实现的,而不是直接声明器,因为直接声明器是不可能的。需要结构体,以便您可以在这些可以终止的不同级别上包含其他数据。
struct list { struct list *next; ... };
现在你可以使用list->next->next->next->...->next
。这实际上只是多级指针间接引用:*(*(..(*(*(*list).next).next).next...).next).next
。而且当它是结构的第一个成员时,.next
基本上是无操作的,因此我们可以将其想象为***..***ptr
。
这种方式并没有什么限制,因为链接可以通过循环而不是像这样的巨大表达式来遍历,而且结构可以很容易地被变成圆形。
因此,换句话说,链表可能是解决问题添加另一层间接性的终极示例,因为您在每次推操作时都要动态进行。
list->next
和 list->next->next
是相同类型;否则我们就必须构建一个无限的类型。) - KazLOAD R1, [R1]
。除了“保存地址的字”,没有涉及任何类型。声明的类型与否不决定间接引用和它有多少级。 - KazLOAD R1, [R1]
就会进入无限循环。 - Kaz理论上:
您可以有任意多层间接引用。
实际上:
当然,任何消耗内存的东西都不能无限制地进行,由于主机环境中可用的资源限制,实际上会有限制。因此,实现对于支持的最大限制应有适当的文档说明。所以在所有这些工件中,标准没有规定最大限制,但它确实指定了下限。
以下是参考信息:
C99标准5.2.4.1翻译限制:
- 在声明中修饰算术、结构、联合或void类型的12个指针、数组和函数声明符(以任何组合形式)。
这明确了每个实现必须支持的下限。请注意,在注释中,标准进一步说明:
18) 尽可能避免强制实施固定的翻译限制。
*
运算符,并且每个重载都返回该系列中其他类型的对象,则此类链接函数调用可能会导致堆栈溢出。 - Nawaz正如其他人所说,“理论上”是没有限制的。然而,出于兴趣,我使用 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;
}
*
的数量翻倍直到出错,然后倒退一个数量级的 *
直到可以运行为止。接着,在这个区间内进行二分查找,找到第一个失败的点。整个测试不到一秒钟就完成了。 - James Kanze听起来很有趣。
在Windows 7上的Visual Studio 2010中,您可以拥有1011个级别,然后会出现以下错误:
致命错误 C1026: 分析器堆栈溢出,程序过于复杂
在Ubuntu上的gcc编译器中,100k+的*
没有崩溃!我猜硬件是限制。
(测试只用了一个变量声明)
*
节点都移入堆栈。 - Kaz没有限制,可以参考指针::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 */
如果你的意思是“在程序难以阅读之前可以使用多少级指针”,那么这是个人口味问题,但是有一个限制。两级间接引用(指向某个指针的指针)是常见的。超过这个级数会比较难以轻松思考;除非没有其他选择,否则不要这样做。
如果你的意思是“运行时可以拥有多少级指针间接引用”,那么没有限制。这一点对于循环列表特别重要,在其中每个节点都指向下一个节点。你的程序可以永远跟随指针。
g++
在 98242 处会因内部错误而中止。我预计实际限制将取决于机器和负载。 我也不认为这会成为真实代码中的问题。) - James Kanze指向函数的指针会使它变得更有趣。
#include <cstdio>
typedef void (*FuncType)();
static void Print() { std::printf("%s", "Hello, World!\n"); }
int main() {
FuncType const ft = &Print;
ft();
(*ft)();
(**ft)();
/* ... */
}
如此处所示,这将产生:
Hello, World!
Hello, World!
Hello, World!
它不涉及任何运行时开销,因此您可以堆叠它们,直到编译器无法处理该文件为止。
没有限制。指针是一块内存,其内容是一个地址。
正如你所说的
int a = 10;
int *p = &a;
指向指针的指针也是一个变量,它包含另一个指针的地址。
int **q = &p;
这里的q
是指向指针p
的指针,而p
已经持有a
的地址。
指向指针的指针并没有什么特别之处。因此,持有另一个指针地址的指针链条没有限制。
即。
int **************************************************************************z;
允许。
每个C++开发人员都应该听说过臭名昭著的三星程序员。
似乎有一个神奇的“指针屏障”必须掩盖。
C2网站上的引用:
三星程序员
C程序员的评级系统。您的指针间接性越高(即在变量前有更多“*”),您的声望就越高。没有星号的C程序员几乎不存在,因为几乎所有非平凡的程序都需要使用指针。大多数人都是一星程序员。在旧时代(好吧,我还年轻,至少对我来说这看起来像是旧时代),偶尔会发现由三星程序员编写的代码,并因敬畏而颤抖。
有些人甚至声称,他们见过涉及函数指针的三星代码,涉及多层间接寻址。对我来说听起来像UFO一样真实。
请注意这里有两个可能的问题:在C类型中,我们可以实现多少级指针间接引用,以及我们可以将多少级指针间接引用塞入单个声明符中。
C标准允许对前者施加最大限制(并为此提供最小值)。但是可以通过多个typedef声明来规避这一限制:
typedef int *type0;
typedef type0 *type1;
typedef type1 *type2; /* etc */
所以,最终这是一个与C程序的大小/复杂度有关的实现问题,这取决于编译器的具体规定。
std::shared_ptr<shared_ptr<shared_ptr<...shared_ptr<int>...>>>
这样的东西。 - josefx(pow (std::shared_ptr, -0.3))<T> x;
的-0.3间接层级。 - user180247