*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
必须在此点之前递增。
我的问题是关于以下代码行,摘自 "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
必须在此点之前递增。