C - 为什么指向指针与指向数组的指针不一样?

时间:2013-08-05 05:42:28

标签: c arrays pointers

如果我写:

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的指针并且有效吗?为什么不呢?

4 个答案:

答案 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