Elb*_*ira 5 c arrays pointers kernighan-and-ritchie
在pg.K&R的109,我们看到:
void writelines(char *lineptr[], int nlines)
{
while (nlines -- > 0) printf("%s\n", *lineptr++);
}
Run Code Online (Sandbox Code Playgroud)
我对*lineptr ++究竟做了什么感到困惑.根据我的理解,printf需要一个char指针,所以我们提供*lineptr.然后我们将lineptr增加到数组中的下一个char指针?这不是非法的吗?
在页99,K&R写道"数组名称不是变量;结构如a = pa [其中a是数组,pa是指向数组的指针]和++是非法的."
继续阅读!在p的最底部.99
作为函数定义中的形式参数,
Run Code Online (Sandbox Code Playgroud)char s[];和
Run Code Online (Sandbox Code Playgroud)char *s;是等价的; 我们更喜欢后者,因为它更明确地说参数是一个指针.
即你永远不能将数组(不是变量)传递给函数.如果你声明一个看起来像是一个数组的函数,它实际上需要一个指针(这是一个变量).这是有道理的.函数参数不是变量会很奇怪 - 每次调用函数时它都可以有不同的值,所以它肯定不是常量!
lineptr不是一个阵列; 它是指向指针的指针.请注意,postincrement运算符的++优先级高于dereference运算符*,因此会发生以下情况lineptr++:
lineptr 增加以指向数组中的下一个元素lineptr++是旧值lineptr,即指向数组中当前元素的指针*lineptr++ 取消引用它,所以它是数组中当前元素的值因此,while循环遍历指向的数组中的所有元素lineptr(每个元素都是a char*)并将它们打印出来.
可能更容易想象*lineptr++如下:
*(lineptr++)
Run Code Online (Sandbox Code Playgroud)
在那里,指向char*s 数组的指针被移动到数组的下一个元素,即从lineptr[0],移动到lineptr[1].(由于指针的后缀增量,在解除引用后会出现指针的增量.)
所以基本上,发生以下事情:
lineptr[0](类型char*)通过引用检索.lineptr.)lineptr[1],再次从步骤1重复该过程.亚当·罗森菲尔德选择的答案是错误的。coobird的答案也是。因此,我对这两个答案都投了反对票。
Adam Markowitz 的解释*lineptr++是正确的,但他没有回答主要问题这是否是合法的 C99 代码。只有汤姆·未来做到了;不幸的是他没有解释*lineptr++。我给他们每人一分。
简而言之,lineptr是一个变量,可以作为指针进行操作。因此增加指针是合法的。
lineptr是指向字符序列的指针序列的指针。换句话说,它是指向字符串数组的第一个字符串的指针。根据代码,我们可以假设字符串是以空('\0')结尾的字符序列。 nlines是数组中字符串的数量。
while 测试表达式是nlines-- > 0. nlines--是后减量(因为--位于变量的右侧)。因此在之后执行因此,无论测试结果如何,它都会在执行测试
因此,如果nlines作为参数给出的值为0,则首先执行测试并返回false; 循环中的指令不被执行。请注意,since无论如何都会递减,循环后nlines的值将为。nlineswhile-1
如果nlines == 1,测试将返回true并nlines递减;循环中的指令将被执行一次。请注意,执行这些指令时, 的nlines值为0。当再次进行测试时,我们又回到了 时的情况nlines == 0。
该printf指令使用*lineptr++表达式。它是指针的后增量(++位于变量的右侧)。这意味着先计算表达式,然后在使用后执行增量。因此,在第一次执行时,printf会收到字符串数组第一个元素的副本,它是指向字符串第一个字符的指针。仅在此之后才递增lineptr。下次printf执行时,lineptr指向第二个元素,并在打印第二个字符串后移动到第三个元素。这是有道理的,因为我们显然想要打印第一个字符串。如果 Adam Rosenfield 是对的,那么第一个字符串将被跳过,最后我们将尝试打印最后一个字符串之外的字符串,这显然是一件坏事。
因此,该printf指令是以下两条指令的简洁形式
printf("%s\n", *lineptr);
++lineptr; // or lineptr++, which is equivalent but not as good. lineptr += 1; is ok too.
Run Code Online (Sandbox Code Playgroud)
请注意,根据经验,当预增量和后增量的作用相同时,出于性能原因,预增量更可取。编译器会小心地为你切换它。嗯,大多数时候。只要有可能,最好由预操作员自己进行,因此始终使用它。一旦您自己在 C++ 中实现了后增量和预增量,原因就会变得更加明确。