*p++->str :理解 -> 的评估

*p++->str : Understanding evaluation of ->

我的问题是关于以下代码行,摘自 "The C Programming Language" 第二版:

*p++->str;

书上说这行代码在访问 str 指向的任何内容后递增 p。

我的理解如下:

我的问题:

我的问题是关于此表达式中最高优先级运算符 (->) 的求值。我相信评估这个运算符意味着评估两个操作数,然后应用运算符。

从->运算符的角度看,左操作数是p还是p++?据我了解,两者 return 的值相同。

但是,如果第一个选项是正确的,我会问"how is it possible for the evaluation of the -> operator to ignore the presence of the ++"。

如果第二个选项正确,我会问"doesn't the evaluation of -> in this case then require the evaluation of a lower precedence operator ++ here (and the evaluation of ++ completes before that of ->)"?

要理解表达式 *p++->str,您需要理解 *p++ 是如何工作的,或者一般来说,后缀增量是如何在指针上工作的。

*p++ 的情况下,p 指向的位置的值在指针 p.
递增之前被取消引用 n1570 - §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). [...]. The value computation of the result is sequenced before the side effect of updating the stored value of the operand.

*p++->str 的情况下,++-> 具有相同的优先级并且高于 * 运算符。根据运算符优先级和关联性规则,此表达式将用括号括起来 *((p++)->str)

这里的一个重要说明是优先级和结合性与求值顺序无关。因此,尽管 ++ 具有更高的优先级,但不能保证 p++ 将首先被评估。这意味着表达式 p++(在表达式 *p++->str 中)将根据上面引用的标准规则进行评估。 (p++)->str 将访问 str 成员 p 指向,然后它的值被解除引用,然后 p 的值在最后一个和下一个序列点之间的任何时间递增。

后缀 ++-> 具有相同的优先级。 a++->b 解析为 (a++)->b,即 ++ 首先完成。

*p++->str;执行如下:

  • 表达式解析为 *((p++)->str)-> 是一个 meta-postfix 运算符,即 ->foo 是所有标识符 foo 的后缀运算符。后缀运算符的优先级最高,其次是前缀运算符(例如 *)。结合性并不真正适用:只有一个操作数,并且只有一种方法可以使用给定的运算符 "associate" 它。

  • p++ 被评估。这会产生 p 的(旧)值并安排更新,将 p 设置为 p+1,这将在下一个序列点之前的某个时间点发生。调用此表达式的结果 tmp0.

  • tmp0->str 被评估。这等效于 (*tmp0).str:它取消引用 tmp0,它必须是指向结构或联合的指针,并获得 str 成员。调用此表达式的结果 tmp1.

  • *tmp1 被评估。这取消引用 tmp1,它必须是一个指针(指向一个完整的类型)。调用此表达式的结果 tmp2.

  • tmp2 被忽略(表达式在空上下文中)。我们到达 ; 并且 p 必须在此点之前递增。