为什么在括号中包含增量运算符没有区别?

时间:2016-10-27 10:28:17

标签: c increment parentheses

为什么这样做是相同的,文档在哪里备份呢?

我的老师坚持认为“z =(y ++)”应首先执行y ++,然后将结果归因于z。

所以这样:

int z, y = 10;
z = (y++);
printf("%d", z); //z = 10 or 11? and why?

谢谢。

5 个答案:

答案 0 :(得分:5)

你的老师错了。在C中,语句z = (y++);z = y++;必须相同。

根据section 6.5.2.4 of N1570(C11的标准草案):

  

后缀++运算符的结果是操作数的值。作为副作用,操作数对象的值递增(即,将相应类型的值1添加到其中)。 [...]在更新操作数的存储值的副作用之前,对结果的值计算进行排序。

postfix ++运算符和括号都具有相同的值:它们只传递其操作数的值。因此,yy++(y)(y++)(y)++都具有相同的值:y的值,表达式已经过评估。

postfix ++唯一不同的是,它在计算其操作数(紧接在它之前的表达式)之后有一个副作用 sometime 。如果是z = (y++); printf("%d", z);,则会发生后缀++的副作用

  • 后,表达式y的值为"计算" (这只是在这种情况下读取变量)和
  • 之前 printf("%d", z);语句,因为复合语句(大括号之间的任何语句列表)都具有排序语义。

除此之外,在完全修改y时无法控制。这也是z = y++ = y++这样的语句具有未定义行为的原因:第一个y++的副作用可能发生在第二个y++的副作用之前或期间或之后。

答案 1 :(得分:3)

是的,它是一样的。这由标准C,ISO 9899:2011 6.5 / 3中的运营商优先规则保证。括号是具有最高优先级(6.5.1)的主表达式,高于后缀++运算符(6.5.2),后者的优先级高于=运算符(6.5.16)。

意味着所有这些都是100%等价的:

z = y++;
(z) = y++;
z = (y++);
(z) = (y++);
(z = y++);

所有这些情况都将评估y,将该值分配给z,然后将y递增1.

(Postfix ++行为定义为:"在更新操作数的存储值的副作用之前,对结果的值计算进行排序。")

但请注意,将++运算符与其他运算符混合被认为是不好的做法,因为它具有更新值的内置副作用。这可以轻松地创建错误,例如y=y++;本来就是一个严重的错误。此外,单行上的多个操作员通常难以阅读。

因此,编写该表达式的规范方法是:

z = y;
y++;

答案 2 :(得分:1)

只有在表达式中有更多运算符时才会出现括号的优点,即在运算池中首先执行括号中的运算

int z, y = 10;
z = (y++);
printf("%d", z);

在你的程序中,括号与增量运算符无关。 增量在赋值后发生(因为后增量)因此输出为10

答案 3 :(得分:0)

  1. 首先了解预增量和后增量。
  2. 如果您应用大括号,后增量的动作将保持不变并不重要。括号只是一个为编译器提供指导但不能对其进行编译的工具。有多个这样的场景,其中括号不会产生任何影响。 例如
  3. printf("%d %d",fun1(),(fun2()))这里即使fun2在大括号中,也不保证会首先调用它。

    同样,它只是对编译器的请求。编译器可能会也可能不会接受此请求,具体取决于其他规则。

答案 4 :(得分:0)

  

我的老师坚持认为“z =(y ++)”应首先执行y ++,然后将结果归因于z。

我会说,这里写的“老师”是对的,但有人误解了原因。首先完成y++,然后将结果分配给z。这与a=(b+c)中的说法相同。首先完成b+c,然后将该表达式的结果分配给a。这是一个老生常谈,这就是任务。 (我们不要将序列点混合到这里,因为序列点不涉及这个特定的问题)

我认为有人混淆的是y++的含义。这是一个具有价值和副作用的表达。无论括号如何,表达式的值都不会改变,就像b+c不会改变一样。在z = EXPRESSION;中将分配表达式的值,无论你在其周围放置多少个括号。

把它想象成一个功能。 z = y++;可以被视为z = function();。函数内部的作用与分配给z的内容无关,只有返回值很重要。这就是表达式可以被视为。