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

时间:2019-06-30 15:39:26

标签: c operator-precedence side-effects associativity

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

*p++->str;

这本书说,这行代码在访问任何str指向后都会递增p。

我的理解如下:

  • 优先级和关联性表示运算符的评估顺序为

    1. ->
    2. ++
    3. *
  • 后缀增量运算符++产生一个值(即其操作数的值),并且具有在下一个序列点(即以下;)之前递增此操作数的副作用。

  • 优先级和关联性描述的是运算符的求值顺序,而不是运算符的操作数的求值顺序。

我的问题:

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

从->运算符的角度来看,左操作数是p还是p ++?我了解这两个返回相同的值。

但是,如果第一个选项正确,我会问“如何对->运算符进行求值而忽略++的存在”。

如果第二个选项是正确的,我会问“在这种情况下,不对->求值,然后在这里要求对一个较低优先级的运算符++求值(并且++的求值先于->的求值)”?

2 个答案:

答案 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必须在此点之前增加。