为什么++(* p)没有给出l值所需的错误?

时间:2017-09-16 05:21:20

标签: c arrays pointers lvalue

#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 ,为什么编译器没有给出错误?

5 个答案:

答案 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]