如果我写:
char string[] = "some string";
char **ptr = &string;
printf("%s\n",*ptr);
它不打印任何内容并发出警告:warning: initialization from incompatible pointer type [enabled by default]
现在,如果我写下以下内容:
char *string = "another string";
char **ptr = &string;
printf("%s\n",*ptr);
它可以正常工作。
不应string[]
衰减到类似于*string
的指针并且有效吗?为什么不呢?
答案 0 :(得分:9)
在这种情况下,这不是衰变的作用方式。 See the C faq:
6.12问: 由于数组引用会衰减成指针,如果
arr
是数组,那么arr
和&arr
之间的区别是什么?A:在标准C中,
&arr
产生一个指向整个数组的指针,指向数组的指针。
所以,当你这样做时:
char string[] = "some string";
char **ptr = &string;
赋值失败,因为&string
的类型是“指向长度为12的char数组的指针”。你可以写一下:
char (*ptr)[12] = &string;
哪个(虽然几乎肯定不是你想要做的)读取“声明ptr作为指向12个字符数组的指针”
如果你真的想要一个指向指针的指针,那么你总是可以使用一个中间变量:
char string[] = "some string";
char *ptr = string;
char **doublepointer = &ptr;
printf("%s",*doublepointer);
答案 1 :(得分:4)
有一个概念,通过名称指向一个数组。你正在使用一个指向数组的指针,而这不是这样做的方法。如果您想指向一个指向数组的指针,请尝试以下方式获得所需的输出。
char string[] = "some string";
char (*ptr)[]=&string;
printf("%s",*ptr);
答案 2 :(得分:0)
实际上,如果我可以添加到Timothy的答案中,char (*ptr)[12] = &string;
类型的指针是相当不寻常的,因为它是指向特定类型和大小的数组的指针。
让我们看看当我们将地址增加1之前和之后打印地址时会发生什么:
char string[] = "some string";
char (*ptr)[12] = &string;
printf("Before: %p\n", (void*)(ptr));
printf("After: %p\n", (void*)(ptr+1));
打印哪些:
Before: 0xbfec44e0
After: 0xbfec44ec
注意在第二种情况下指针是如何移动12块内存的。由于指针知道它指向的类型的大小,因此在数组的情况下也适用,不仅适用于任何普通旧类型。在我们的例子中是12。
对这个here有深刻的解释,你很想读。
答案 3 :(得分:0)
第一个string
是一个数组。它的地址指向这个数组:
+-+-+-+-+-+-+-+-+-+-+-+
|s|o|m|e| |s|t|r|i|n|g|
+-+-+-+-+-+-+-+-+-+-+-+
这个数组的地址是指向一个数组的指针,所以*char[]
。
第二个string
是指向同一个字符串的指针(可能,但取决于实现)在只读空间中:
+------+ +-+-+-+-+-+-+-+-+-+-+-+
| addr | -> |s|o|m|e| |s|t|r|i|n|g|
+------+ +-+-+-+-+-+-+-+-+-+-+-+
此指针的地址为**char
。