我在讲座中研究过后缀和前缀运算符仅在获得分号后才增加值。
把你的讲师发给我,这样我就可以拿棒球棒给他礼貌地指出他的错误。
正是当前置或后缀的副作用++
and --
被应用的是未指定,除了要求它发生在下一个序列点之前。在这样的表达中
x = a++ * b
a
之后可能会立即更新a++
已评估,或者更新可能会推迟到a++ * b
已被评估并将结果分配给x
,或介于两者之间的任意位置。
这就是为什么像这样的表达式i++ * i++
and printf("%d %d", c++, c)
and a[i++] = i
还有很多其他的都是坏juju。根据编译器、优化设置、周围代码等,您将得到不同的结果。语言标准明确保留了行为不明确的因此编译器没有义务“做正确的事情”,无论正确的事情是什么。请记住,定义未定义的行为 is
3.4.3
1 undefined behavior
behavior, upon use of a nonportable or erroneous program construct or of erroneous data,
for which this International Standard imposes no requirements
2 NOTE Possible undefined behavior ranges from ignoring the situation completely with unpredictable
results, to behaving during translation or program execution in a documented manner characteristic of the
environment (with or without the issuance of a diagnostic message), to terminating a translation or
execution (with the issuance of a diagnostic message).
3 EXAMPLE An example of undefined behavior is the behavior on integer overflow.
这是一个经过深思熟虑的设计决策 - 未指定这些操作的顺序的理由是让实现自由地重新安排评估顺序以达到优化目的。然而,作为这种自由的交换,某些操作将不会产生明确的结果。
请注意,编译器可以自由地try检测这些病例并发出诊断;printf("%d %d", c++, c);
很容易被发现,但在一般情况下这将是一个很难检测到的问题。想象一下如果这样写的话printf("%d %d", (*p)++, c)
; if p
指着c
,那么行为是未定义的,否则没关系。如果p
被分配在不同的翻译单元中,那么在编译时就无法知道这是否是一个问题。
这个概念并不难理解,但却是最容易被误解的概念之一。taught)C 语言方面。毫无疑问,这就是为什么 Java 和 C# 语言规范强制对所有内容采用特定的求值顺序(所有操作数都从左到右求值,并且所有副作用都会立即应用)。