2011-08-30 73 views
6

下面的代码混淆了我一下:C指针质疑

char * strcpy(char * p, const char * q) { 
while (*p++=*q++); 
//return 
} 

这是strcpy函数的执行剥离。从这段代码中,我们看到指针p和q被赋值,而不是解除引用,q被赋值给p,直到达到\ 0 char。让我感到困惑的是while循环的第一次迭代。据我所知,数组的指针指向数组的第一个元素。在这段代码中,指针在赋值发生之前是增量赋值的(right?),所以从我的理解中,第一个元素永远不应该被赋值给p(因为后赋值发生在赋值之前),但它确实存在,我不理解后面的魔法。任何人都足以解释为什么? :-)

由于

+6

你对post/pre的定义似乎是倒退的。 Post =之后,Pre =之前。这里的后递增表示第一个字符将被复制,然后指针将递增。 – Marlon

+0

为什么C++标签(和标题)?这是一个C库函数。 –

+1

看起来像我的完美有效的C++代码@Paul。那么为什么不* C++标签? –

回答

9

因为++是变量后,它们不会递增,直到后的表达进行评估。这就是为什么它是后增量运算符;预增量是前缀(++ p)。 * ++ p将写入第二个位置,* p ++写入第一个位置。

+1

哦SH *** T,我真的需要睡觉:S。谢谢Kevin:S – Davita

1

表达式(* q ++)的右侧将在* p ++之前进行求值,并且两者只会在分配发生后才会增加。

从右到左阅读声明并记住后续增量(q ++而不是++ q)在该行中的其他内容解决后发生。

*q --> dereference q 
= --> assign the value 
*p --> to p 

增加两者。

这样做直到q p取q的元素= 0,即它到达空终止符时。

2

p++后递增指针p。因此p的当前值在p递增之前由尊敬运算符*运行。

你的推理会一直正确,如果while循环被写成如下:

while (*++p=*++q); 

在这种情况下,增量将间接引用之前发生。

2

不,增量发生在赋值后。

如果它是*(++p),则指针p将递增,然后分配。

1

这是一个strcpy函数的剥离实现。从这段代码中,我们看到指针p和q被赋值,而不是解除引用,q被赋值给p,直到达到\ 0 char。

它恰好相反。在*p处的值被设置为*q,然后两个指针递增。

当您有int foo = bar++时,增量发生在foo设置后。有它发生第一次你会做int foo = ++bar

+1

@Marlon,你为什么编辑我的文章?你已经颠倒了意思,这是不正确的。 * p被设置为* q,而不是相反,除非我有一个完整的脑部放屁和缺少的东西。 – Alex

1

q++价值为q
++q值是q+1

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; 
} 
+0

不完全正确,因为您的while(* p)正在查看下一个字符,而不是刚刚复制的字符。 – Neil

+0

@尼尔 - 啊,傻了。谢谢你的收获! – Dawson

2

表达x++++x既具有结果(值)和副作用

结果的表达式x++是当前值x。所述副作用是,x的内容通过1

表达++x结果递增是x加1的电流值的副作用是与上述相同。

请注意,在评估表达式后,不必立即应用副作用;它只需要在下一个序列点之前应用。例如,给定的码

x = 1; 
y = 2; 
z = ++x + y++; 

没有保证的是,表达y++求值之前的x内容将被修改,或甚至之前的++x + y++结果被分配给z(既不=也不+运营商引入一个序列点)。 表达式++x的计算结果为2,但有可能变量x在分配z之后可能不包含值2。

请务必记住,x++ + x++等表达式的行为明确为未由语言标准定义;没有(好的)方法来预测表达式的结果是什么,或者在评估之后将包含什么值x

后缀运算符具有比一元运算符的优先级高,所以像*p++表达式解析为*(p++)(即,你申请的*操作者表达p++的结果)。同样,表达式p++的结果是当前值p,所以while (*p++=*q++);不会跳过第一个元素。

请注意,自动增量/减量运算符的操作数必须是左值(本质上,指的是可以读取或修改存储器的内存位置的表达式)。表达式x++++x的结果是而不是左值,因此您不能编写诸如++x++(x++)++++(++x)之类的东西。你可能写一些像++(*p++)p++是不是一个左值,但*p++是),虽然这可能会让你任何人读你的代码打耳光。