arrays - 对 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 初学者来说很困惑。
解决方案
首先,让我们为您的两个变量指定不同的名称和内容,以便我们可以清楚地区分它们。
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
.
推荐阅读
- python - py2neo 递归匹配
- symfony - 如何将请求通道记录到日志文件中?
- i18next - i18next:自定义 json 格式,带有翻译局的注释
- java - 无法解析 Java 中“WebDriver”中的方法“setFileDetector”
- javascript - 我可以更改需要将 matomo 跟踪脚本添加到我的网站的方式吗?
- android - 将大型 VideoFile 读取到 ByteArray 时出现 OutOfMemoryException
- pandas - 为什么`pandas.DataFrame()` 这么慢?
- qml - QML中如何根据文本大小制作标签大小?
- laravel - 我有一个想法使用 auth 中间件来检索用户的产品
- python - 将python海龟绘图导出到视频