我的问题是关于以下代码行,摘自“ The C Programming Language”第二版:
*p++->str;
这本书说,这行代码在访问任何str指向后都会递增p。
我的理解如下:
优先级和关联性表示运算符的评估顺序为
后缀增量运算符++产生一个值(即其操作数的值),并且具有在下一个序列点(即以下;)之前递增此操作数的副作用。
优先级和关联性描述的是运算符的求值顺序,而不是运算符的操作数的求值顺序。
我的问题:
我的问题是关于此表达式中最高优先级运算符(->)的求值。我认为,评估此运算符意味着先评估两个操作数,然后应用该运算符。
从->运算符的角度来看,左操作数是p还是p ++?我了解这两个返回相同的值。
但是,如果第一个选项正确,我会问“如何对->运算符进行求值而忽略++的存在”。
如果第二个选项是正确的,我会问“在这种情况下,不对->求值,然后在这里要求对一个较低优先级的运算符++求值(并且++的求值先于->的求值)”?
答案 0 :(得分:6)
要了解表达式*p++->str
,您需要了解*p++
的工作方式,或者通常了解指针后缀增量的工作方式。
在使用*p++
的情况下,在指针p
递增之前,已取消引用位置p
指向的值。
n1570-§6.5.2.4/ 2:
后缀++运算符的结果是操作数的值。副作用是,操作数对象的值增加了(即,向其添加了适当类型的值1)。 [...]。 结果的值计算先于更新操作数存储值的副作用进行排序。
在*p++->str
的情况下,++
和->
的优先级相同且高于*
运算符。根据运算符优先级和关联性规则,该表达式将用*((p++)->str)
括起来。
这里的一个重要说明是优先级和关联性与评估顺序无关。因此,尽管++
的优先级较高,但不能保证将首先评估p++
。这意味着表达式p++
(在表达式*p++->str
中)将按照上述标准引用的规则进行求值。 (p++)->str
将访问str
成员p
指向的位置,然后其值被取消引用,然后p
的值将在最后一个序列点与下一个序列点之间的任何时间递增。 / p>
答案 1 :(得分:6)
后缀++
和->
具有相同的优先级。 a++->b
解析为(a++)->b
,即首先完成++
。
*p++->str;
执行如下:
该表达式解析为*((p++)->str)
。 ->
是元后缀运算符,即->foo
是所有标识符foo
的后缀运算符。后缀运算符的优先级最高,其后是前缀运算符(例如*
)。关联性并不真正适用:只有一个操作数,只有一种将它与给定运算符“关联”的方法。
p++
被评估。这将产生p
的(旧)值,并计划将p
设置为p+1
的更新,该更新将在下一个序列点之前的某个时刻发生。调用此表达式的结果tmp0
。
tmp0->str
被评估。这等效于(*tmp0).str
:它取消引用tmp0
,该引用必须是指向结构或联合的指针,并获得str
成员。调用此表达式的结果tmp1
。
*tmp1
被评估。这将取消引用tmp1
,该引用必须是一个指针(指向完整类型)。调用此表达式的结果tmp2
。
tmp2
被忽略(该表达式在void上下文中)。我们到达;
,并且p
必须在此点之前增加。