以下代码让我感到困惑:
char * strcpy(char * p, const char * q) {
while (*p++=*q++);
//return
}
这是strcpy
函数的精简实现。从此代码中,我们看到指针p
和q
递增,然后取消引用,q
被分配给p
,直到达到\0
个字符。< / p>
我希望有人解释while循环的第一次迭代。
答案 0 :(得分:9)
因为 这就是为什么它是后增量运算符;预增量是前缀(++
位于变量之后,所以在 之后 ++p
)。 *++p
将写入第二个位置,*p++
写入第一个位置。
答案 1 :(得分:2)
p++
后指针p
后递增。因此,在p
递增之前,参与运算符*
会对p
的当前值进行操作。
如果while
循环编写如下,那么你的推理是正确的:
while (*++p=*++q);
在这种情况下,增量将在解除引用之前发生。
答案 2 :(得分:2)
不,增量发生在作业之后。
如果是*(++p)
,则指针p
将递增并在指定之后递增。
答案 3 :(得分:2)
表达式x++
和++x
同时包含结果(值)和副作用。
表达式x++
的结果是x
的当前值。 副作用是x
的内容增加1.
表达式++x
的结果是x
的当前值加1. 副作用与上面相同。< / p>
请注意,评估表达式后不必立即应用副作用;它只需要在下一个序列点之前应用。例如,给定代码
x = 1;
y = 2;
z = ++x + y++;
无法保证在评估表达式x
之前,甚至在将y++
的结果分配给++x + y++
之前修改z
的内容=
和+
运算符引入了序列点。 表达式 ++x
的计算结果为2,但在分配x
之前,变量z
可能不包含值2。
重要的是要记住,x++ + x++
这样的表达式的行为是显式未定义的语言标准;没有(好的)方法来预测表达式的结果是什么,或者在评估之后将包含什么值x
。
后缀运算符的优先级高于一元运算符,因此像*p++
这样的表达式被解析为*(p++)
(即,您将*
运算符应用于表达式的结果{ {1}})。同样,表达式p++
的结果是p++
的当前值,因此p
不会跳过第一个元素。
请注意,自动增量/减量运算符的操作数必须是 lvalue (实际上,是一个表达内存位置的表达式,以便可以读取或修改内存)。表达式while (*p++=*q++);
或x++
的结果是而不是左值,因此您无法编写++x
或++x++
或{{ 1}}。你可以写一些类似(x++)++
的内容(++(++x)
不是左值,但是++(*p++)
是),尽管这可能让你被阅读代码的任何人打耳光。
答案 4 :(得分:1)
表达式(* q ++)的右侧将在* p ++之前进行评估,并且两者都将在赋值发生后递增。
从右到左阅读语句,并记住在行中的其他所有内容都已解决后发生后增量(q ++而不是++ q)。
*q --> dereference q
= --> assign the value
*p --> to p
增加两者。
这样做直到q p取q的元素= 0,即它到达空终止符时。
答案 5 :(得分:1)
这是strcpy函数的剥离实现。从这段代码中,我们看到指针p和q是增加的,而不是取消引用,q被赋值给p,直到达到\ 0 char。
它反过来发生了。 *p
处的值设置为*q
,然后两个指针都递增。
当你有int foo = bar++
时,foo被设置后会发生增量。要先让它发生,你会int foo = ++bar
答案 6 :(得分:1)
q++
的值是q
++q
的值为q+1
答案 7 :(得分:1)
while
循环的条件是执行后增量。等价地:
while (true) {
char* old_p = p;
const char* old_q = q;
++p; // or p++;
++q; // or q++;
*old_p = *old_q;
if (*old_p == '\0')
break;
}