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
的值在 获得其值后递增 。
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
的更新可以按任何顺序发生,甚至可以同时发生(交错或并行)。
这是一个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
的值在 获得其值后递增 。
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
的更新可以按任何顺序发生,甚至可以同时发生(交错或并行)。