首页 > 解决方案 > 对 C 处理字符串的方式感到困惑

问题描述

为什么不

   char *name = "asd";
   printf("%p\n%p", (void *)&name, (void *)&name[0]);

给出相同的输出

char name[] = "asd";
printf("%p\n%p", (void *)&name, (void *)&name[0]);

我读过 C 将字符串作为指向它们的第一个字符的指针,直到它到达'\0'但上面的代码不喜欢它,所以对于 C 初学者来说很困惑。

标签: arrayscpointers

解决方案


首先,让我们为您的两个变量指定不同的名称和内容,以便我们可以清楚地区分它们。

char *namep = "asd";
char namea[] = "zxc";

这些导致数据结构可能如下所示:

       +-------+
namep: |   *   |
       +---|---+
           |
          /
         |
         V
       +---+---+---+----+
       | a | s | d | \0 |
       +---+---+---+----+

       +---+---+---+----+
namea: | z | x | c | \0 |
       +---+---+---+----+

现在让我们看看你的两个printf电话:

printf("%p\n%p", (void *)&namep, (void *)&namep[0]);

现在,&namep给你namep指针的地址。
但是&namep[0]会为您提供指向字符串 ( a) 中第一个字符的地址。如果你打印了

printf("%p\n", (void *)namep);

你会看到同样的事情。

printf("%p\n%p", (void *)&namea, (void *)&namea[0]);

在这里,&namea给你数组的地址。
&namea[0]给你它的第一个字符 ( z) 的地址——这是同一个地方。事实上,由于特殊处理(数组“衰减”为指针),如果你说过

printf("%p\n", (void *)namea);

你也会看到同样的事情。

您问:

我读过 C 将字符串作为指向它们的第一个字符的指针,直到它到达'\0'.

这是正确的。

假设你写了代码

char *p;
for(p = namep; *p != '\0'; p++)
    putchar(*p);

这将打印您的namep字符串,asd. 这里没有什么神秘之处。 namep已经是一个指针,指向字符串的第一个字符,所以这段代码有自己的指针p,它开始指向指向的位置namep,并打印指向的字符,直到它到达终止符\0

可能更令人惊讶的是,您可以使用以下内容执行完全相同的操作namea

char *p;
for(p = namea; *p != '\0'; p++)
    putchar(*p);

这也适用于打印zxc,如果您不相信我,我鼓励您将它输入到您的 C 编译器中并尝试一下。

现在,你可能会问,如果p是指针又namea是数组,循环初始化怎么p = namea工作?这又是由于数组对指针的“衰减”。同样,当你尝试namea像这样使用 ' 值时,你得到的——被分配的值p——自动成为指向namea' 的第一个元素的指针。当然,这正是你想要的。 p从那里开始,并打印字符,直到找到 a \0,从而打印zxc.


推荐阅读