指针上多个增量运算符的求值顺序

时间:2014-11-25 16:23:10

标签: c pointers operators increment

无法理解,如何评估以下陈述:

++*++ptr and *ptr++++

根据我的理解,首先会给我lValue,因为在应用*之后它会给出不能用于++运算符的值。但是,结果却相反。请解释一下。

第二个语句给出错误:batch3.c:6:21:错误:需要左值作为递增操作数   printf("%d",* ptr ++++);

3 个答案:

答案 0 :(得分:2)

首先,一些standardese

6.5.2.4后缀增量和减量运算符

约束

1后缀增量或减量运算符的操作数应具有原子的,合格的, 或不合格的真实或指针类型,并且应该是可修改的左值

语义

2后缀++运算符的结果是操作数的值。作为副作用, 操作数对象的值递增(即,相应类型的值为1 添加到它)。 参见附加算子的讨论和复合赋值 有关约束,类型和转换以及操作对其影响的信息 指针。结果的值计算在副作用之前排序 更新操作数的存储值。关于不确定的顺序 函数调用,postfix ++的操作是单个评估。对象上的Postfix ++ with atomic type是一个带有memory_order_seq_cst的读 - 修改 - 写操作 记忆顺序语义。 98)
...
6.5.16分配操作员
...
3赋值运算符将值存储在左操作数指定的对象中。一个 赋值表达式具有赋值后的左操作数的值, 111) 但不是 左值。赋值表达式的类型是左操作数将具有的类型 在左值转换后。更新左操作数的存储值的副作用是 在左右操作数的值计算之后排序。评估 操作数没有排序。

强调我的。

该文本墙的结果是表达式ptr++++ptr的结果不是左值。但是,两个表达式都会产生指针值,因此它们可能是一元*运算符的操作数,*ptr++*++ptr 的结果可能是左值。

这就是++*++ptr有效的原因;你正在递增*++ptr的结果,这可能是一个左值。但是,*ptr++++被解析为*(((ptr)++)++)(后缀++的优先级高于一元*); ptr++的结果是第二个++的操作数,但由于ptr++的结果不是左值,编译器会抱怨。如果您将其写为(*ptr++)++,那么表达式将是有效的。

简而言之:

++*++ptr     - valid, equivalent to ++(*ptr++)
*++++ptr     - invalid, equivalent to *(++(++ptr)), result of ++ptr is not an lvalue
++++*ptr     - invalid, equivalent to ++(++(*ptr)), result of ++*ptr is not an lvalue
*ptr++++     - invalid, equivalent to *((ptr++)++), result pf ptr++ is not an lvalue
(*ptr)++++   - invalid, equivalent to ((*ptr)++)++, result of (*ptr)++ is not an lvalue
(*ptr++)++   - valid

答案 1 :(得分:1)

++运算符优先于*

因此指针将首先递增,然后解除引用。

*p++

首先

p++

然后*p++

对于++,必须有一个需要递增的值。但是下面的表达式并没有为++提供左值。 p++不是可修改的左值。

*ptr++++;

答案 2 :(得分:1)

考虑到这两个表达式是分开的(注意and已定义<iso646.h>),这里会发生什么:

第一个++*++ptr相当于++(*(++ptr)),因为前缀++和一元*具有相同的precedence,并且从右到左的共生性为他们都。请参阅以下example作为说明:

#include <stdio.h>

int main(void)
{
    int a[] = {1, 2};
    int *ptr = a;

    ++(*(++ptr));

    printf("%d\n", a[0]);
    printf("%d\n", a[1]);

    return 0;
}

结果:

1
3

后一个表达式不可编译,因为ptr++子表达式不是可修改的左值。请注意,postix ++具有更高的优先级,*(间接运算符)及其关联性是从左到右。