int *p,x=5;
p=&x;
x=++*p;
printf("%d\n",x);
x=*p++;
printf("%d\n",x);
x=++*p;
printf("%d",x);
尽管我知道前缀++首先增加值然后存储它,而后缀++首先存储值然后增加它。但是在最后一行中,为什么在printf语句中打印1?
答案 0 :(得分:0)
x=++*p;
将内容从5更改为6,然后将6存储在x中。 (前缀++和*具有相同的优先级,因此前缀运算符的运算符关联性从右到左起作用。)
x=*p++;
意味着后缀++首先被评估,因为它具有更高的优先级。但是p
的实际更改只会在执行整个表达式之后发生,因此*p
中的值6将在发生之前存储在x中。
请注意,++表示p
现在指向实际有效内存位置之外的一个int
。只要不取消引用变量,在C中都可以允许这种指向超出分配范围的第一项的特殊情况。
x=++*p;
这里的指针被取消引用,这是不允许的,因此这是一个错误(与++无关)。这是不确定的行为,任何事情都可能发生。对您而言,这次恰好打印1。对我来说,这次打印的是8958。但是,由于它是未定义的行为错误,因此程序也可能崩溃或以其他随机方式启动。
请注意,在同一表达式中将++
与其他运算符混合使用是不好的做法。 ++运算符非常危险,因为它们会引入书写的副作用,并且这种副作用可能无法与表达式的其余部分配合。
答案 1 :(得分:0)
伦丁有一个很好的,彻底的答案。我希望这不是题外话...
最后一条语句恰好是将指针递增为整数。如果将打印语句更改为此,您将看到p
的增量。
printf("%d, %p\n",x,p);
使用gcc
,我得到以下输出:
6,0x7ffeee3a92a4
6,0x7ffeee3a92a8
-298151255,0x7ffeee3a92a9
在这里,您可以看到前两行的指针都增加了sizeof(int)
(4字节)。但是,未定义的行为发生在最后一条语句中,在我的情况下,该语句打印出垃圾,因为它不再与4B对齐。在这种情况下,碰巧现在将指针视为一个int(因为它现在将值加1)。
答案 2 :(得分:0)
这里有一个更好的例子:
int main()
{
int *p,x[4]={1,2,3,4};
p=x;
++*p;
printf("%2d %2d %2d %2d\n",x[0], x[1], x[2], x[3]);
printf("p: %p x: %p\n", (void *)p, (void *)x);
*p++;
printf("%2d %2d %2d %2d\n",x[0], x[1], x[2], x[3]);
printf("p: %p x: %p\n", (void *)p, (void *)x);
++*p;
printf("%2d %2d %2d %2d\n",x[0], x[1], x[2], x[3]);
printf("p: %p x: %p\n", (void *)p, (void *)x);
}
the output is
2 2 3 4
p: 0x7ffc7ef56670 x: 0x7ffc7ef56670
2 2 3 4
p: 0x7ffc7ef56674 x: 0x7ffc7ef56670
2 3 3 4
p: 0x7ffc7ef56674 x: 0x7ffc7ef56670