【发布时间】:2009-10-10 18:46:09
【问题描述】:
如标题所示,有什么区别,因为这两个似乎得到了相同的结果?
【问题讨论】:
如标题所示,有什么区别,因为这两个似乎得到了相同的结果?
【问题讨论】:
不,它们不一样。假设d是一个指向int的指针:
int n = 0;
int* d = &n;
*d++; // d++ then *d, but d++ is applied after the statement.
(*d)++; // == n++, just add one to the place where d points to.
我认为在 K&R 中有一个例子,我们需要将一个 c-string 复制到另一个:
char* first = "hello world!";
char* second = malloc(strlen(first)+1);
....
while(*second++ = *first++)
{
// nothing goes here :)
}
代码很简单,将first指向的字符放入second指向的字符中,然后在表达式之后递增两个指针。当然,当最后一个字符“\0”被复制时,表达式会变成false,然后就停止了!
【讨论】:
*foo++ 编写的复制过程,它比使用 GCC 的 foo[i++] 慢方式。
sizeof(first) 已经说明了终止空值。无需添加 1。我想你在写这篇文章时已经想到了 strlen :)
自增++比解引用*具有更高的运算符优先级,所以*d++自增指针d指向数组中的下一个位置,但++的结果是原始指针d,所以 *d 返回指向的原始元素。相反,(*d)++ 只是增加指向的值。
例子:
// Case 1
int array[2] = {1, 2};
int *d = &array[0];
int x = *d++;
assert(x == 1 && d == &array[1]); // x gets the first element, d points to the second
// Case 2
int array[2] = {1, 2};
int *d = &array[0];
int x = (*d)++;
assert(x == 1 && d == &array[0] && array[0] == 2);
// array[0] gets incremented, d still points there, but x receives old value
【讨论】:
在官方 C 术语中,这些表达式确实会为您提供相同的结果,正如它们应该提供的那样。在正确的术语中,非空表达式的“结果”是该表达式的计算结果。你的两个表达式的初始值都是*d,所以结果是一样的也就不足为奇了。
但是,C 中的每个表达式都添加到“结果”之外,有零个或多个所谓的“副作用”。而这两种表达方式的副作用是完全不同的。第一个表达式递增指针“d”的值。第二个表达式增加 '*d' 的值(指向的值)。
【讨论】:
第一个递增指针,第二个递增指向的值。
作为一个实验,试试这个:
int main() {
int x = 20;
int *d = &x;
printf("d = %p\n", d);
int z = (*d)++;
printf("z = %d\n", z);
printf("d = %p\n", d);
int y = *d++;
printf("y = %d\n", y);
printf("d = %p\n", d);
}
【讨论】:
它们确实返回相同的结果,但程序中的状态变化完全不同。
如果我们只是扩展操作,这是最容易理解的。
x = *d++;
// same as
x = *d;
d += 1; // remember that pointers increment by the size of the thing they point to
x = (*d)++;
// same as
x = *d;
*d += 1; // unless *d is also a pointer, this will likely really just add 1
【讨论】:
我手边没有编译器。
a = (*d)++;
b = (*d);
是a==b吗?我不这么认为。
【讨论】: