为什么*p++
首先将值分配给i
,然后递增p
指针,即使++
后递增优先级较高,并且关联性来自从右到左?
int main()
{
int a[]={55,66,25,35,45};
int i;
int *p=&a;
printf("%u \n",p);
i=*p++;
printf(" %u %d",p,i);
printf("\n %d",*p);
return 0;
}
4056 4060 55 66
答案 0 :(得分:8)
后缀++
运算符的语义是表达式p++
的计算结果为p
的 current 值,并且是的副作用 p
递增。实际上,i = *p++;
与
i = *p;
p++;
前缀 ++
的语义是表达式的求值为p
加一的当前值,并且效果p
增加。 i = *++p;
实际上与
i = *(p + 1);
p++;
优先级不控制求值顺序-它仅控制解析(哪些运算符与哪些操作数分组)。
答案 1 :(得分:4)
在指针和数组如何协同工作方面似乎存在一些误解。
表达式&a
是指向数组本身的指针,类型为int (*)[5]
。
您似乎期望得到一个指向第一个元素的指针,该指针将是&a[0]
或纯a
(因为它会衰减到指向数组第一个元素的指针):>
int *p = a;
它的工作并非巧合,因为指向数组的指针恰好指向与第一个元素的位置相同的地址。地址相等,但是&a
和&a[0]
的类型不同。这种语义上的差异确实至关重要。
关于++
运算符的问题,只是它的工作原理。
后缀增加或减少运算符的结果是 old 值。因此,当您执行p++
时,会在增加之前得到 old 指针。
如果我们服用
i = *p++;
(有点简化)等同于
int *temporary_old_p = p;
p = p + 1;
i = *temporary_old_p;
此外,指针的"%u"
格式无效。要打印void *
指针(确实需要正确的转换),您应该使用"%p"
格式说明符。
格式说明符和参数类型不匹配会导致未定义的行为。
关于*(&a + 1)
的问题,让我们绘制数组a
在内存中的样子,并用一些箭头显示指针:
+------+------+------+------+------+------ | a[0] | a[1] | a[2] | a[3] | a[4] | .... +------+------+------+------+------+------ ^ ^ | | &a[0] | | | &a &a + 1
由于&a
的类型为int (*)[5]
,因此&a + 1
的类型也应为int (*)[5]
。
如果我们取消对指针&a
的引用(如在*(&a)
中那样),那么我们将获得实际的数组a
。像a
这样的数组会衰减到指向其第一个元素&a[0]
的指针。该指针指向与&a
相同的位置(如上面的“图形”所示)。
如果将&a
更改为&a + 1
,则在取消引用中得到*(&a + 1)
。这是“第二”数组(是否存在)。就像*(&a)
是五个int
的数组一样,*(&a + 1)
也是如此。该数组衰减为指向其第一个元素&(*(&a + 1))[0]
的指针。
或者也许认为&a
等于&a + 0
。这样就很容易看出*(&a)
等于*(&a + 0)
。而且我们知道*(&a)
等于a
,等于&a[0]
,这也意味着*(&a + 0)
必须等于&(*(&a + 0))[0]
。这样应该可以轻松了解&(*(&a + 1))[0]
可能是什么。