为什么这样做是相同的,文档在哪里备份呢?
我的老师坚持认为“z =(y ++)”应首先执行y ++,然后将结果归因于z。
所以这样:
int z, y = 10;
z = (y++);
printf("%d", z); //z = 10 or 11? and why?
谢谢。
答案 0 :(得分:5)
你的老师错了。在C中,语句z = (y++);
和z = y++;
必须相同。
根据section 6.5.2.4 of N1570(C11的标准草案):
后缀
++
运算符的结果是操作数的值。作为副作用,操作数对象的值递增(即,将相应类型的值1添加到其中)。 [...]在更新操作数的存储值的副作用之前,对结果的值计算进行排序。
postfix ++
运算符和括号都具有相同的值:它们只传递其操作数的值。因此,y
,y++
,(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)
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
的内容无关,只有返回值很重要。这就是表达式可以被视为。