它是未定义的,因为它x
在序列点之间修改了两次。标准说它是未定义的,因此它是未定义的。
我知道的那么多。
但为什么?
我的理解是,禁止这样做可以使编译器更好地进行优化。当发明C时,这本来是有道理的,但现在看来似乎是一个很弱的论点。
如果我们今天要重新发明C,那么我们会这样做吗,还是可以做得更好?
或者,也许还有一个更深层次的问题,那就是很难为此类表达式定义一致的规则,因此最好禁止它们?
因此,假设我们今天要重新发明C。我想为诸如的表达式建议简单的规则x=x++
,在我看来,这些规则比现有规则更有效。
与现有规则或其他建议相比,我希望您对建议的规则有意见。
建议规则:
- 在序列点之间,未指定评估顺序。
- 副作用立即发生。
没有涉及未定义的行为。表达式的计算结果等于或等于该值,但肯定不会格式化硬盘(奇怪的是,我从未见过x=x++
格式化硬盘的实现)。
示例表达式
x=x++
-定义明确,不会改变x
。
首先,x
将其递增(立即x++
求值时),然后将其旧值存储在中x
。x++ + ++x
-递增x
两次,计算为2*x+2
。
尽管可以首先评估任一侧,但结果要么是x + (x+2)
(首先是左侧),要么是(首先是(x+1) + (x+1)
右侧)。x = x + (x=3)
-未指定,x
设置为x+3
或6
。
如果首先评估右边,则为x+3
。也有可能x=3
首先被评估,所以是3+3
。在任何一种情况下,x=3
赋值都会在x=3
评估时立即发生,因此存储的值将被另一个赋值覆盖。x+=(x=3)
-定义明确,设置x
为6。
您可以说这只是上述表达式的简写。
但是我要说的是,+=
必须在之后执行x=3
,而不是分为两个部分(读取x
,评估x=3
,添加和存储新值)。
有什么优势?
一些评论提出了这一点。
我当然不认为x=x++
在任何普通代码中都应使用诸如此类的表达式。
实际上,我要比这严格得多-我认为单独使用x++
in 的唯一好用法x++;
。
但是,我认为语言规则必须尽可能简单。否则,程序员只是不了解它们。禁止在序列点之间两次更改变量的规则当然是大多数程序员都不了解的规则。
一个非常基本的规则是:
如果A有效,B有效,并且它们以有效方式组合,则结果有效。
x
是有效的L值,x++
是有效的表达式,并且=
是将L值和表达式组合在一起的有效方法,那么为什么x=x++
不合法呢?
C标准在这里是一个例外,该例外使规则复杂化。您可以搜索stackoverflow.com并查看此异常使人们感到困惑的程度。
所以我说-摆脱这种混乱。
===答案摘要===
为什么这样
我试图在上一节中解释-我希望C规则要简单。优化的潜力:
这确实使编译器有了一些自由,但是我没有看到任何使我相信它可能很重要的东西。
大多数优化仍然可以完成。例如,a=3;b=5;
即使标准指定了顺序,也可以重新排序。诸如之类的表达式a=b[i++]
仍然可以进行类似的优化。您不能更改现有标准。
我承认,我不能。我从没想过我可以真正改变标准和编译器。我只想考虑是否可以采取其他措施。
x
给自己没有多大意义,如果您想增加x
,可以说x++;
-不需要分配。我要说它不应该仅仅因为很难记住应该发生什么而被定义。