为啥 ++(*p) 没有给出 l-value required 错误?

Posted

技术标签:

【中文标题】为啥 ++(*p) 没有给出 l-value required 错误?【英文标题】:Why ++(*p) is not giving l-value required error?为什么 ++(*p) 没有给出 l-value required 错误? 【发布时间】:2017-09-16 05:21:20 【问题描述】:
#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,为什么编译器不报错?

【问题讨论】:

【参考方案1】:

*p 将是常量值 [...]

不,和arr[0]一样。

所以

++(*p);

一样
++(p[0]);

一样
++(arr[0]);

这是一个完全有效的陈述。

【讨论】:

【参考方案2】:

对象指针取消引用本身不会产生指针指向的值。相反,它会生成一个引用该值的左值。用标准的话来说:

一元* 运算符表示间接。如果操作数指向一个 函数,结果是一个函数指示符;如果它指向一个 对象,结果是一个指定对象的左值。如果操作数 类型为“类型指针”,结果类型为“类型”。

(C2011,6.5.3.2/4;强调)

一元* 因此是一类可以被认为对对象的身份进行操作的运算符,而不是对其值进行操作。 &amp; 运算符和sizeof 运算符的某些用途也可以认为属于此类。

【讨论】:

是的。每个其他答案都忘记提及取消引用运算符的结果:)。【参考方案3】:

*p 将是常量值

不,不会。 *pa[0] 当你做 int *p = arr; 时。 a[0] 不是常数值,由于它们相同,*p 也不是常数值。

结果是这样的:

++(*p);

相当于:

++(a[0]);

它增加了数组第一个位置的元素,你可以清楚地看到。

但是回头看++(*p),可以看到:

*p 取消引用指针,产生一个左值。 然后我们有(*p),括号中的左值。 ++(*p) 将预增量运算符应用于左值,即值,因此不会产生编译器错误。

【讨论】:

【参考方案4】:

为什么++(*p) 没有给出 l-value required 错误?

指针上的取消引用运算符产生一个左值。 因此,*p 是一个左值,并且在其上使用预增量运算符是有效的。

【讨论】:

【参考方案5】:

请注意您使用的两个语句:

++*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-value required 错误的原因是因为在您的声明中:

++*p; // *p is not a constant, it is same as a[0]

【讨论】:

"*p is not a constant, it points to a[0]" 不,*p a[0] @alk ya,用词不当,词点在那里用词不当。会更新。谢谢:) "its value is equal to a[0]" 这不仅仅是相等,甚至更多:它是相同的内存。 可能是语言问题?在这种情况下,“相等”和“相同”是不一样的...... :-) @alk 同意了。纠正了。

以上是关于为啥 ++(*p) 没有给出 l-value required 错误?的主要内容,如果未能解决你的问题,请参考以下文章

move semantic/ r-value /L-value (copy from stakcoverflow)

C语言错误:left operand must be l-value

为啥这个涉及 floor 函数的公式没有给出我期望的结果?

为啥这两个指针减法会给出不同的结果?

为啥基本身份验证总是使用 restTemplate 给出错误 403?

为啥我们只在私人部分给出 Q_OBJECT?