3

如果我写:

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

4 回答 4

9

在这种情况下,衰变不是这样的。请参阅 C 常见问题解答

6.12 问: 由于数组引用衰减为指针,如果是数组,和arr有什么区别?arr&arr

答: 在标准 C 中,&arr产生一个指向整个数组的指针,类型为pointer-to-array-of-T。

所以,当你这样做时:

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);
于 2013-08-05T05:53:28.983 回答
4

有一个按名称指向数组的指针的概念。您正在使用指向数组的指针,这不是这样做的方法。如果你想指向一个数组的指针,试试下面的方法你会得到所需的输出。

char string[] = "some string";
char (*ptr)[]=&string;
printf("%s",*ptr);
于 2013-08-05T05:50:20.940 回答
0

实际上,如果我可以添加到蒂莫西的答案,char (*ptr)[12] = &string;指针的类型是相当不寻常的,因为它是指向特定类型和大小的数组的指针。

让我们看看在我们将其地址加一之前和之后打印它的地址时会发生什么:

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。

这里有对此的深入解释,您可能想阅读。

于 2013-08-05T06:28:48.397 回答
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

于 2013-08-05T06:36:39.413 回答