相关代码的用途
您的代码似乎完全错误,因为它增加了var2 指针的目标,该指针也用于结束循环。您不能期望递增值达到零。我会假设(1)你想增加临时指针来迭代一个字符串列表(技术上是一个数组)和(2)你期望一个 NULL 指针作为哨兵。
指针自增问题详解
那么我们写的代码的逻辑是什么?它需要一个字符串数组(文件中的行、名称列表等),对项目进行计数,然后执行您需要做的任何其他事情。输入参数由指向 char 的指针表示,这对初学者来说可能有点混乱。指针在 C 中用于多种用途,一个是指向列表的第一项(技术上是数组)。这就是list 指针(char ** 类型)的情况,它指向一个指针数组(每个类型为char *),该数组又指向一个字节/字符值数组(每个类型char)。
因此,您需要增加一个本地 char ** 指针来迭代项目,并增加一个临时 char * 指针来迭代项目的字符。如果您只想读取数据,则绝不能增加本地(临时)变量以外的任何内容。递增*item 是无稽之谈,并且会以错误的方式更改数据(指针将指向第二个字符而不是第一个字符),并且检查递增的指针是否为 NULL 是双重废话。
换句话说,使用临时指针遍历数组的习惯用法需要以下操作:
- 在每一步都增加临时指针(仅此而已)。
- 检查指针的目标(而不是它指向的地址)的标记值。
更正的代码示例
使用 C99 语法,您可能想要执行以下操作:
void method1(char **list) {
size_t count = 0;
for (char **item = list; *item; item++)
count++;
...
}
旧的语法迫使你这样做:
void method1(char **list) {
char **item;
size_t count = 0;
for (item = list; *item; item++)
count++;
...
}
对于不熟悉指针的人来说更直观的版本:
void method1(char **list) {
size_t count = 0;
for (size_t i = 0; list[i]; i++)
count++;
...
}
注意:count 是多余的,因为它的值与 i 的值保持相同,因此您可以只使用空主体或 while (list[count]) count++; 来执行 for (; list[count]; count++)。
只计算项目的真正功能是:
size_t get_size(char **list)
{
int count = 0;
for (char **item = list; *item; item++)
count++;
return count;
}
当然可以简化为(借用其他答案):
size_t get_size(char **list)
{
int count = 0;
for (; *list; list++)
count++;
return count;
}
感谢非常特殊的情况,其中 (1) 很容易合并 condition 和 increment 以及 (2) 您没有使用正文中的当前项目,可转为:
size_t get_size(char **list)
{
int count = 0;
while (*list++)
count++;
return count;
}
尝试回答 for 与 while 的困境
虽然从技术上讲 while 和 for 循环是等价的,但 for 循环更好地表达了迭代习语方式,因为它将迭代逻辑与其余代码分开,并且因此也使其更可重用,即您可以将相同的 for 标头与不同的主体一起用于列表上的任何其他迭代操作。
原代码中for循环的错误使用
有很多事情应该被认为是不鼓励的:
1) 不要从 for 循环头修改对象。
for (... ; ...; (*item)++)
...
只要item 是指向实际数据的临时指针,任何符合上述模式的代码都会修改目标对象而不是执行循环逻辑。
2) 不要从 for 循环头中解耦任何非循环代码。
char **item = list;
...
for (; *item; *item++)
count++;
for 循环之前的赋值似乎不合适。如果您复制粘贴 for 循环的标头以再次遍历所有列表项,则由于省略了初始化,该列表看起来是空的。
3) 不要在 for 循环头的 increment 中执行任何每个项目的操作。
for (char **item = list; *item++, count++)
;
这里的count++ 根本没有帮助循环,而是执行实际操作(计算一项)。如果您复制粘贴 for 循环的标头并添加实际正文,count 将被修改。
4) 不要对参数使用非描述性的,对临时变量使用简单的名称。
for (char **var2 = var1; *var2; var2++)
count++;
这两个变量的用途不同,但它们的名称几乎相同,只是用一个数字来区分。您如何准确命名它们取决于上下文和偏好。
注意:有些人也更喜欢显式比较 NULL 而不是依赖于指针的布尔评估。不过,我不是其中之一。 Stack Exchange 似乎将 list 突出显示为关键字,但我认为 C 或 C++ 中没有这样的关键字。