关于C编程的问题

时间:2010-01-03 02:42:50

标签: c operators

int a, b;
a = 1;
a = a + a++;
a = 1;
b = a + a++;

printf("%d %d, a, b);

输出:3,2

第3行和第5行有什么区别?

4 个答案:

答案 0 :(得分:19)

你正在做的事情是未定义的。

您无法更改要分配给的变量的值。

你也不能改变带有副作用的变量的值,也尝试在同一个表达式的其他地方使用同一个变量(除非有sequence point,但在这种情况下没有)。 +的两个参数的评估顺序是未定义的。

因此,如果两行之间存在差异,那么第一行是未定义的,原因有两个,而第5行只是因为一个原因而未定义。但重点是第3行和第5行都是未定义的,并且要么做错了。

答案 1 :(得分:6)

你在第3行所做的事情是未定义的。 C ++具有“序列点”的概念(通常由分号分隔)。如果你在每个序列点修改一个对象不止一次,这是非法的,正如你在第3行所做的那样。正如section 6.5 of C99所说:

  

(2)在前一个和下一个序列点之间,一个对象应具有其存储的值   通过表达式的评估最多修改一次。此外,先前的价值   应该只读以确定要存储的值。

由于第二句,第5行也未定义。您阅读a以获取其值,然后将其用于a++中的其他作业。

答案 2 :(得分:4)

第3行未定义,第5行未定义。

编辑:

正如Prasoon正确指出的那样,两者都是UB。

由于以下原因,未定义简单表达式a + a++

  1. 运算符+不是序列点,因此每个操作数的副作用可能以任何顺序发生。
  2. a最初为1
  3. 可能出现两种可能的[合理]情景之一:

    1. 首先评估第一个操作数,a

      a)其值1将存储在寄存器R中。没有副作用。

      b)评估第二个操作数a++。它也计算为1,并被添加到同一寄存器R。作为副作用,a的存储值设置为2。

      c)当前位于R的添加结果将写回aa的最终值为2。

    2. 首先评估第二个操作数a++

      a)它被评估为1并存储在寄存器R中。 a的存储值增加到2

      b)读取第一个操作数a。它现在包含值2,而不是1!它已添加到R

      c)R包含3,此结果将写回a。添加的结果现在是3,而不是2,就像我们的第一种情况一样!

  4. 简而言之,您不能依赖此类代码。

答案 3 :(得分:4)

a++是一个修复后的操作符,它获取的值然后递增它。

因此,对于2,3行:
a = 1
a = 1 + 1,a递增 a变为3 (注意,执行这些操作的顺序可能因编译器而异,并且a也很容易变为2)

第4,5行的


a = 1
b = 1 + 1,a递增 b变为2,a变为2. (由于未定义的行为,b也可能变成a ++中的3个在a之前处理)

请注意,除了理解后缀运算符的工作方式之外,我真的不建议使用这个技巧。使用不同的编译器进行编译时,undefined behavior 会得到不同的结果

因此,这不仅是一种不必要的混乱方式,而是一种不可靠,最糟糕的做法。

编辑:还有其他人指出,这实际上是未定义的行为。