【发布时间】:2017-01-10 14:00:18
【问题描述】:
在尝试用 C 语言遍历字符串数组的方法时,我开发了以下小程序:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef char* string;
int main() {
char *family1[4] = {"father", "mother", "son", NULL};
string family2[4] = {"father", "mother", "son", NULL};
/* Loop #1: Using a simple pointer to step through "family1". */
for (char **p = family1; *p != NULL; p++) {
printf("%s\n", *p);
}
putchar('\n');
/* Loop #2: Using the typedef for clarity and stepping through
* family2. */
for (string *s = family2; *s != NULL; s++) {
printf("%s\n", *s);
}
putchar('\n');
/* Loop #3: Again, we use the pointer, but with a unique increment
* step in our for loop. This fails to work. Why? */
for (string s = family2[0]; s != NULL; s = *(&s + 1)) {
printf("%s\n", s);
}
}
我的具体问题涉及 Loop #3 的失败。通过调试器运行时,循环 #1 和 #2 成功完成,但最后一个循环由于未知原因而失败。我不会在这里问这个问题,除非这表明我对“&”运算符有一些严重的误解。
我的问题(和目前的理解)是这样的:family2 是一个指向字符的数组。因此,当s 设置为family2[0] 时,我们有一个(char*) 指向“父亲”。因此,取&s 应该给我们等价于family2,指向预期指针衰减后family2 的第一个元素。那为什么不呢,
*(&s + 1) 指向下一个元素,如预期的那样?
非常感谢,
生命危机
编辑——更新和经验教训:
以下列表是所有相关事实和解释的摘要,这些事实和解释解释了为什么第三个循环不像前两个那样工作。
-
s是一个单独的变量,它保存来自变量family2[0]的值的副本(指向字符的指针)。即,这两个等效值位于内存中的不同位置。 -
family2[0]到family2[3]是内存的连续元素,s在此空间中不存在,尽管它确实包含与我们循环开始时存储在family2[0]中的相同值。 - 前两个事实意味着
&s和&family2[0]不相等。因此,向&s添加一将返回一个指向未知/未定义数据的指针,而向&family2[0]添加一将根据需要为您提供&family2[1]。 - 此外,第三个 for 循环中的更新步骤实际上不会导致 s 在每次迭代时在内存中向前迈进。这是因为
&s在我们循环的所有迭代中都是不变的。这就是观察到的无限循环的原因。
感谢大家的帮助!
生命危机
【问题讨论】:
-
什么是
string? C 没有字符串类型。 -
注意代码块顶部的 typedef!谢谢!
-
啊,是的!所以另一个警告适用:永远不会
typedef一个指针!它混淆了代码,向命名空间发送垃圾邮件,并且使限定符正确的代码变得很困难,如果不是不可能的话。 -
typedef指针永远不是一个好主意。阅读this。 -
根据您的编辑,您似乎对答案感到满意。如果是这样,你应该accept one of them。
标签: c arrays pointers memory-address