C 运算符中的求值顺序

Order of Evaluation in C Operators

按照 C,PostIncrement(a++) > Dereference(*) > Assignment(=) 当我在下面的 c 代码段中执行此操作时,

#include <stdio.h>

int main(){

    int arr[]= {1,2,3};
    int *p = a;

    *p++ = 3;

    for(int i=0;i<3;i++){
        printf("%d ",arr[i]);  
    }

}

输出: 3 2 3

但是如果我们在此语句中应用优先顺序,

 *p++ = 3;

语句将按以下顺序计算:

  1. p++ 将被评估
  2. *p 将被取消引用。
  3. 然后 3 将使用赋值运算符赋值给 *p

如果我们应用上面的顺序, 指向数组 arr 开头的 p 将首先递增并指向数组的第二个元素。然后第二个元素的地址将被取消引用,然后 3 将被分配给第二个索引。所以我们的预期输出应该是 1 3 3 但是我得到的输出是 3 2 3.

我知道我的预期输出不正确。如果您在此处解释编译器输出的计算顺序,将会很有帮助。

post 递增表达式的结果是操作数 递增之前的值。因此,即使 *p++ 中的 ++ 确实比 * 具有更高的优先级,后者应用于 p++ 表达式的结果,即刚才提到,初始值p.

根据 C 标准(6.5.2.4 后缀递增和递减运算符)

2 The result of the postfix ++ operator is the value of the operand. As a side effect, the value of the operand object is incremented (that is, the value 1 of the appropriate type is added to it). See the discussions of additive operators and compound assignment for information on constraints, types, and conversions and the effects of operations on pointers. The value computation of the result is sequenced before the side effect of updating the stored value of the operand. With respect to an indeterminately-sequenced function call, the operation of postfix ++ is a single evaluation. Postfix ++ on an object with atomic type is a read-modify-write operation with memory_order_seq_cst memory order semantics.

因此在这个声明中

 *p++ = 3;

表达式 p++ returns 指针的当前值 p 即指向数组第一个元素的指针。指向数组第一个元素的指针被解除引用。

所以这个声明

 *p++ = 3;

不等同于语句

p++;
*p = 3;

"语句将按以下顺序求值:

p++ 将被评估 *p 将被取消引用。 然后 3 将使用赋值运算符赋值给 *p

Post 增量运算符不是那样工作的。您可以这样假设以便更好地理解。

  • 当 p++ 被评估时,首先,它的当前值存储在一个临时位置,然后发生增量。
  • 所有剩余操作都对存储在临时位置的值执行。
  • 对于后续语句,使用增量值。

优先级仅决定运算符与操作数的分组 - 它不控制表达式计算的顺序。优先规则只确定

*p++ = 3;

应该解析

*(p++) = 3; // as opposed to (*p)++ = 3 or *(p++ = 3)

不是按特定顺序执行操作。

++–– 运算符有一个 结果 和一个 副作用 。 postfix ++ 的结果是操作数的当前值;副作用是增加操作数。您的表达式在逻辑上等同于

tmp = p;
*tmp = 3;
p = p + 1;

需要注意的是,对 *tmp 的赋值和对 ptr 的更新可以按任何顺序发生,它们甚至可以交错或并行执行。