2010-10-20 35 views
0

可能重复:
In what order does evaluation of post-increment operator happen?以L值使用后缀增量

考虑下面的代码片断(在C):


uint8_t index = 10; 
uint8_t arr[20]; 

arr[index++] = index; 

当我编译此同gcc,它将arr [10]设置为10,这意味着后缀增量在整个赋值表达式之后才会被应用锡永。我发现这有点令人惊讶,因为我期待增量返回原始值(10),然后递增到11,从而将arr [10]设置为11.

我见过很多关于增量运算符的其他文章在RValues中,但不在LValue表达式中。

谢谢。

+1

但是,这些其他帖子应该指出你在C中使用的概念来规范这些表达式的有效性,即序列点,否?阅读完所有这些内容后,您应该能够发出合格的猜测。 – 2010-10-20 14:06:09

+0

-1为当天无用的后续问题。看到上面的两个评论为我的理由。 – 2010-10-20 14:45:44

回答

4

一些standard语言:

6.5表达式

1表达式是运营商和操作数的序列,可指定一个 值的计算,或者,指定的对象或功能,或产生副作用,或者执行其组合。

2在上一个和下一个序列点之间,对象的存储值 最多只能通过评估表达式进行修改。 72)此外,先验值只能读取以确定要存储的值。 73)

3运算符和操作数的分组由语法指示。 74)除以后指定(对于函数调用 ()&&||和逗号运营商),子表达式的评估顺序和顺序侧效果发生都没有说明。

第2段明确呈现表达式a[i++] = i undefined;之前的值i不只是读取以确定i++的结果。因此,任何结果都是允许的。

除此之外,您不能依赖++运算符的副作用在评估表达式后立即应用。对于像

a[i++] = j++ * ++k 

的唯一保证一个表达式是,表达j++ * ++k结果被分配给结果表达a[i++];但是,每个子表达式a[i++]j++,和++k可以是以任何顺序进行评价,和副作用(分配给a[i],更新i,更新j和更新k)可以以任何顺序来施加。

+0

感谢您的详细解答! – ssfrr 2010-10-20 15:10:50

+0

在这里,你说我可以按任何顺序评估i ++,j ++和++ k。但是'*'的关联性是否使得++ ++之前需要评估j ++? – 2012-12-30 14:39:24

+1

优先级和关联性只能保证*表达式被解析*。对于像'a + b * c'这样的表达式来说,所有的保证就是把'b * c'的*结果*加到'a'的结果上。无法保证评估各个子表达式“a”,“b”和“c”的顺序。 – 2012-12-31 11:29:59

1

线

arr[index++] = index; 

导致未定义的行为。阅读C标准了解更多详情。

您应该知道的本质是:您不应该在同一个语句中读取和更改变量。

+1

为什么选择C++标准? – 2010-10-20 14:01:36

+2

你的文本里有两个'+'太多了;-) – 2010-10-20 14:02:19

+0

这个问题是关于C的,具体的。 C标准也可能没有定义行为,但我不确定在哪里寻找。 – ssfrr 2010-10-20 14:04:05

1

赋值操作从右向左工作,即首先计算的表达式的右部分,然后将其分配给左部分。

+0

首先,该操作根据第6.5节第2段未定义,因此*任何*结果都是允许的。其次,根据第6.5节第3段,任何两个序列点之间评估表达式的顺序(以及所应用的副作用)均为*未指定*;除了某些运算符(函数调用'()','&&','||','?:'和逗号运算符,这些运算符都保证从左到右的评估),您无法保证特定的评估顺序。 – 2010-10-20 14:39:09