理解字符串指针数组

Understanding Array of Character String Pointers

我正在尝试了解引用指针时收到的结果 'p'。我已在线发表评论,说明我认为正在发生的事情。

#include <stdio.h>

main()
{
    char *words[] = { "hello", "world" };
    char **p = words;              // p is now pointing to words[0]?

    ++p; // p now points to "world"

    printf("%s\n", *p);            // Prints the character string 'world', pointed to by p
    printf("%c\n", *p[0]);         // Returns 'w'
    printf("%c\n", *p[1]);         // Should return 'o'? Returns garbage
    printf("%c\n", *++p[0]);       // Returns 'o'?
}

我的理解是:

char **p = words;

p 现在指向 words[0] 指向的第一个字符,即 'h''hello'。然后之后:

++p

p 现在指向指针在 words[1] 处指向的第一个字符,即 'w''world'.

结果:

world
w
<blank space>
o

如果*p[0] return是字符'w'。那么,为什么 *p[1] return 垃圾?我试图了解 *words 中的指针指向的内容是如何在内存中组织的,然后 p 在每次调用后指向哪里。

更新

通过更改以下行:

    printf("%d\n", *p[0]);         
    printf("%d\n", *p[1]);         
    printf("%d\n", *++p[0]);      

现在的结果是:

119 // 'w'
1   // 'SOH' -- Start of heading
111 // 'o'

现在,在这种情况下,SOH 字符到底是什么?

您应该使用警告来显示基本错误

a.c:10:5: warning: format ‘%c’ expects argument of type ‘int’, but argument 2 has type ‘char *’ [-Wformat]

*p 是指向字符的指针。 尝试:

printf("%s\n", *p); 


printf("%c\n", *p[1]);

这里p[1]可以是words的第三个元素,因为没有第三个元素你读的是垃圾值。

对于 ++p[0] p[0] 指向 "world"++ 这指向 "orld" 然后与 * 你打印第一个 char 所以 o.

要理解指针,您可以使用 print%p 来查看您指向的地址。

有些误会。

之后的内存布局:

char *words[] = { "hello", "world" };

看起来像:

words[0]    words[1]
|           |
v           v
+-----------+-----------+
|   ptr1    |    ptr2   |
+-----------+-----------+


ptr1
+---+---+---+---+---+------+
| h | e | l | l | o | '[=11=]' |
+---+---+---+---+---+------+

ptr2
+---+---+---+---+---+------+
| w | o | r | l | d | '[=11=]' |
+---+---+---+---+---+------+

你说:

char **p = words;              // p is now pointing to world[0]?

如果你的意思是words[0],那么你是对的。

你也说,

That p now points to the first character pointed to by words[0]

这是不正确的。 p 的类型是 char**。你可以说 *p 指向 words[0].

指向的第一个字符

关于程序的输出...

你有一行:

++p;

此行更改 p 使其指向 words[1]

printf("%c\n", *p); // Should return 'w'? But returns garbage

是未定义行为的原因,因为 *p 的类型不是代表 charint*p 的类型是 char*,而不是 char

printf("%c\n", *p[0]);         // Returns 'w'

打印 w 因为 p[0] 等于 ptr2。从内存布局可以看出,*ptr2 的计算结果为 'w'。因此,您会在输出中得到 w

printf("%c\n", *p[1]); // Should return 'o'? Returns garbage

也是导致未定义行为的原因。

由于运算符优先级,*p[1]等价于*(p[1]),后者等价于*(*(p+1))。由于 p 已经指向 words[1](p+1) 指向无效内存。