5

来自K&R的The C Programming Language的第 123 页:

(p++)->x 在访问 x 后递增 p。(最后一组括号是不必要的。为什么?)

为什么没有必要考虑到->bind 比 强++

编辑:将给定的表达式与 进行对比++p->x,后者被评估为++(p->x)会增加x,而不是p。所以在这种情况下,括号(++p)->x必要的,如果我们想增加,我们必须写p

4

5 回答 5

5

唯一可能的解释是:

p++(->x)

这并不意味着什么。它甚至无效。以有效方式解释这一点的唯一(p++)->x可能方法是.

于 2013-02-18T22:03:08.060 回答
4

正是因为-> 绑定比强++。(它没有,谢谢@KerrekSB。)

访问 x增加 p 。

所以首先你访问xp然后你增加p。这完全符合 the->+运算符的求值顺序。

编辑:哇,这些编辑...

因此,当您编写时会发生什么++p->x,它可以被解释为++(p->x)或解释为(++p)->x(实际选择哪个只是语言设计的问题,K&R 认为让它像第一种情况一样评估是个好主意)。问题是这种歧义在 的情况下不存在p++->x,因为它只能解释为(p++)->x。其他替代品 ,p(++->x)p(++->)x实际上p++(->x)只是语法错误的“表达式”。

于 2013-02-18T21:58:47.333 回答
3

最大咀嚼策略表示p++->x分为以下预处理标记:

p然后++然后->_x

p++->x表达式中有两个运算符,后缀++运算符和后缀运算->符。这两个运算符都是后缀运算符,它们具有相同的优先级,并且在解析表达式时没有歧义。p++->x相当于(p++)->x

对于++p->x表达,情况就不同了。

++p->x中, the++不是后缀运算符,它是++一元运算符。C 赋予后缀运算符高于所有一元运算符的优先级,这就是为什么++p->x实际上等同于++(p->x).

编辑:由于史蒂夫的评论,我改变了答案的第一部分。

于 2013-02-18T22:06:19.090 回答
2

后增量和成员访问运算符都是后缀表达式并且绑定相同。考虑到它们适用于左侧的主表达式或后缀表达式,因此不会有歧义。

p++->x

postfix-++ 运算符只能应用于它左边的表达式(即 to p)。

同样 ->x 只能访问其左侧的表达式,即p++. 不需要写那个表达式(p++),但也没有坏处。

您对效果的描述中的“之后”不表示增量和成员访问的时间顺序。它仅表示 的结果p++p增量之前的值,并且该值是用于成员访问的值。

于 2013-02-18T22:05:30.303 回答
1

表达式p++产生一个值为 的指针p。稍后,该++部分被执行,但出于解释表达式的目的,它可能不存在。->x使编译器将成员的偏移量添加x到原始地址p并访问该值。

如果将语句更改为:

p->x; p++;

它会做同样的事情。

从这里可以看出,优先顺序实际上是完全相同的——但这并不重要。

于 2013-02-18T22:00:58.703 回答