C 运算符优先级后缀递增和取消引用

C Operator Precedence postfix increment and dereference

这是一个C新手的另一个天真的问题:在这个页面上,https://en.cppreference.com/w/c/language/operator_precedence,后缀增量的优先级被列为高于指针解引用的优先级。所以我期望在下面的代码中指针首先递增(指向 10)然后取消引用。

#include <stdio.h>

int main()
{
  int a[] = {3, 10, 200};
  int *p = a;
  printf("%d", *p++);
  return 0;
}

但是这段代码仍然输出第一个数组项 (3)。这个概念我错过了什么?

括号优先。

表达式*p++可以用括号括起来为

(*p)++ // incorrect precedence
*(p++) // correct precedence

请注意 p++ 的值是 p 在任何更改之前的值 ,因此正确优先级的净效果与*p 没有蚂蚁反思 副作用 ++。对 p 本身的更改不会改变 *(p++).

的结果

运算符优先级指定如何解析表达式。由于后缀++的优先级高于*,表达式等价于*(p++)。而不是 (*p)++ 这会给它一个完全不同的含义。

但仅仅因为这会强制首先计算 p++,所以它不会影响 ++ 运算符的特性。 C 语言指定此运算符的行为为(来自 C17 6.5.2.4/2):

"The value computation of the result is sequenced before the side effect of updating the stored value of the operand."

这意味着 p++ 在应用 ++ 之前总是给出 p 的值。在这种情况下 p 是一个指针,因此该值将是它在该表达式之前指向的地址。所以代码完全等同于:

int* tmp = p;
p++;
printf("%d", *tmp);

正如您正确假设的那样,表达式 *p++ 的计算结果为 *(p++);也就是说,++ 运算符的优先级高于 * 运算符。

然而,表达式 p++ 的值只是 p 的值(即它的值 增量之前)。该操作的 副作用p 的值在 获得其值后递增

来自this Draft C11 Standard

6.5.2.4 Postfix increment and decrement operators


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). … 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. …

优先级控制哪些运算符与哪些操作数分组。后缀 ++ 的优先级高于一元 * 只是意味着 *p++ 被解析为 *(p++) 而不是 (*p)++.

*(p++) 表示您正在取消引用 p++ 的结果。 p++ 的结果是 p 的当前值。作为 副作用 p 递增。它在逻辑上等同于

tmp = p;
printf( "%d\n", *tmp );
p = p + 1;

其中 printf 调用和对 p 的更新可以按任何顺序发生,甚至可以同时发生(交错或并行)。