来自K&R的The C Programming Language的第 123 页:
(p++)->x 在访问 x 后递增 p。(最后一组括号是不必要的。为什么?)
为什么没有必要考虑到->
bind 比 强++
?
编辑:将给定的表达式与 进行对比++p->x
,后者被评估为++(p->x)
会增加x
,而不是p
。所以在这种情况下,括号是(++p)->x
必要的,如果我们想增加,我们必须写p
。
来自K&R的The C Programming Language的第 123 页:
(p++)->x 在访问 x 后递增 p。(最后一组括号是不必要的。为什么?)
为什么没有必要考虑到->
bind 比 强++
?
编辑:将给定的表达式与 进行对比++p->x
,后者被评估为++(p->x)
会增加x
,而不是p
。所以在这种情况下,括号是(++p)->x
必要的,如果我们想增加,我们必须写p
。
唯一可能的解释是:
p++(->x)
这并不意味着什么。它甚至无效。以有效方式解释这一点的唯一(p++)->x
可能方法是.
正是因为->
绑定比强++
。(它没有,谢谢@KerrekSB。)
访问 x后增加 p 。
所以首先你访问x
,p
然后你增加p
。这完全符合 the->
和+
运算符的求值顺序。
编辑:哇,这些编辑...
因此,当您编写时会发生什么++p->x
,它可以被解释为++(p->x)
或解释为(++p)->x
(实际选择哪个只是语言设计的问题,K&R 认为让它像第一种情况一样评估是个好主意)。问题是这种歧义在 的情况下不存在p++->x
,因为它只能解释为(p++)->x
。其他替代品 ,p(++->x)
和p(++->)x
实际上p++(->x)
只是语法错误的“表达式”。
最大咀嚼策略表示p++->x
分为以下预处理标记:
p
然后++
然后->
_x
在p++->x
表达式中有两个运算符,后缀++
运算符和后缀运算->
符。这两个运算符都是后缀运算符,它们具有相同的优先级,并且在解析表达式时没有歧义。p++->x
相当于(p++)->x
。
对于++p->x
表达,情况就不同了。
在++p->x
中, the++
不是后缀运算符,它是++
一元运算符。C 赋予后缀运算符高于所有一元运算符的优先级,这就是为什么++p->x
实际上等同于++(p->x)
.
编辑:由于史蒂夫的评论,我改变了答案的第一部分。
后增量和成员访问运算符都是后缀表达式并且绑定相同。考虑到它们适用于左侧的主表达式或后缀表达式,因此不会有歧义。
在
p++->x
postfix-++ 运算符只能应用于它左边的表达式(即 to p
)。
同样 ->x 只能访问其左侧的表达式,即p++
. 不需要写那个表达式(p++)
,但也没有坏处。
您对效果的描述中的“之后”不表示增量和成员访问的时间顺序。它仅表示 的结果p++
是p
增量之前的值,并且该值是用于成员访问的值。
表达式p++
产生一个值为 的指针p
。稍后,该++
部分被执行,但出于解释表达式的目的,它可能不存在。->x
使编译器将成员的偏移量添加x
到原始地址p
并访问该值。
如果将语句更改为:
p->x; p++;
它会做同样的事情。
从这里可以看出,优先顺序实际上是完全相同的——但这并不重要。