未定义的行为和序列点
上面的链接讨论的是C++中的序列点和副作用。
简而言之,这意味着在两个序列点之间,如果我们有多个副作用,则副作用的顺序是未指定的。
例如,
int x = 1;
int y = 2;
int z = x++ + y++;
我们可以确定的是z
等于3。之后z
得到 3,x
and y
会增加——有两个副作用,所以我们不知道哪一个先增加。
另外,上面的链接列出了各种序列点。
我的问题是,Java有完全相同的情况吗?我的意思是相同类型的序列点和相同的未定义行为?
与大多数其他流行语言相比,“现代”C 和 C++ 之间的主要区别在于,虽然其他语言允许编译器以未指定的方式在各种极端情况行为中进行选择,但 C 和 C++ 标准的作者并不想将语言限制在可以轻松满足任何类型行为保证的平台上。
给定一个如下结构:
int blah(int x)
{
return x+10 > 20 ? x : 0;
}
Java 精确指定了 x 的所有值的行为,包括那些
这会导致整数环绕;早期 C 编译器的设计
二进制补码机器会产生相同的行为,除了机器
具有不同大小的“int”(16 位、36 位等)将在不同的位置换行
地方。使用其他整数表示形式的机器可能会表现出
然而,情况有所不同。
此外,即使对于“传统”C 编译器来说,这种情况也并不罕见。
表现得好像计算是在更长的类型上执行的。一些
机器有一些可以操作较长类型的指令,并且使用
这些指令和将值保留为更长的类型有时可能是
比将值截断/包装到“int”范围内便宜。在这样的
机器,像上面这样的函数产生结果也就不足为奇了
x 甚至对于溢出 10 以内的值。请注意,Java 会尝试
最大限度地减少实现之间的行为差异,因此不会
通常甚至允许这种程度的行为变化。
然而,现代 C 语言比 Java 又向前迈进了一步。它不仅允许
因为编译器可能会任意保留多余的精度
对于整数值,给定上述函数的现代编译器可能会
推断由于标准将允许编译器做任何事情
如果程序接收到的输入会导致函数接收到一个值
x 大于 INT_MAX-10,编译器应丢弃任何不相关的代码
如果未收到此类输入,则不会产生任何影响。净效应
这是整数溢出会破坏效果前代码
以任意的方式。
因此,Java 与现代 C 的“未定义行为”模型相距两步;
它严格规定了更多的行为,甚至在行为不符合的情况下rigidly定义的实现仍然仅限于从各种可能性中进行选择。除非使用 Unsafe 命名空间中的功能或将 Java 与外部语言链接,否则 Java 程序的行为将受到更多限制,并且即使使用此类构造,Java 程序仍将遵守时间和因果关系的规律,而 C 程序可能不会。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)