#include <stdio.h>
int main()
{
int arr[] = {1, 2, 3, 4, 5};
int *p = arr;
++*p;
p += 2;
printf("%d", *p);
return 0;
}
为什么这段代码没有给出任何编译时错误,我怀疑++*p
被评估为++(*p)
而*p
将是常量值1
,当我们这样做时{ {1}}这不是 l-value ,为什么编译器没有给出错误?
答案 0 :(得分:11)
*p
将是常量值[...]
不,它与arr[0]
相同。
所以
++(*p);
与
相同++(p[0]);
与
相同++(arr[0]);
这是一个非常有效的陈述。
答案 1 :(得分:3)
*p
将是常量值
不,它不会。当你*p
时,a[0]
为int *p = arr;
。 a[0]
不是常量值,因为它们是相同的,*p
也不是常量值。
结果,这个:
++(*p);
相当于:
++(a[0]);
,可以在数组的第一个位置递增元素,如您所见。
但回顾++(*p)
,我们可以看到:
*p
取消引用指针,产生l值。(*p)
,括号中的l值。++(*p)
将预增量运算符应用于l值,即值,因此不应生成编译器错误。答案 2 :(得分:3)
对象指针解除引用本身不会产生指针指向的值。相反,它产生一个引用该值的左值。用标准的话说:
一元
*
运算符表示间接。如果操作数指向a 功能,结果是功能指示符;如果它指向一个 object,结果是指定对象的左值。如果是操作数 有类型&#34;指向类型&#34;的指针,结果类型&#34;类型&#34;。
(C2011,6.5.3.2/4;重点补充)
因此,一元*
是一类运算符,可以被认为是对象的标识,而不是它的值。 &
运算符以及sizeof
运算符的某些用法也可以视为此类别。
答案 3 :(得分:2)
为什么
++(*p)
没有给出l值必需的错误?
指针上的解引用运算符产生左值。
因此,*p
是左值,并且在其上使用预增量运算符是有效的。
答案 4 :(得分:1)
请注意您使用的两个陈述:
++*p; // increments the value pointed by *p at that time `a[0]` by 1
p += 2; // increments the address p is storing by 2
并且没有l值必需错误的原因是因为在你的陈述中:
++*p; // *p is not a constant, it is same as a[0]