12

我通读了几个关于未定义行为和序列点(例如未定义行为和序列点)的非常好的答案,我明白了,

   int i = 1;
   a = i + i++; //this is undefined behaviour

根据 C++ 标准,是未定义的代码。但是,未定义行为背后的更深层原因是什么?使它成为未指定的行为还不够吗?通常的论点是,通过很少的序列点,C++ 编译器可以针对不同的体系结构进行更好的优化,但是不指定它是否也允许这些优化?在

   a = foo(bar(1), bar(2)); //this is unspecified behaviour

编译器也可以优化,它不是未定义的行为。在第一个示例中,a 是 2 或 3 似乎很清楚,所以语义对我来说似乎很清楚。我希望有一个推理,为什么有些事情是未指定的,而另一些是未定义的。

4

5 回答 5

9

并非所有这些优化。例如,Itanium 可以并行执行加法和增量,并且它可能会因为尝试执行此类操作而产生硬件异常。

但这是一个完全的微优化,编写编译器来利用这一点非常困难,而且这是一个极其罕见的架构可以做到这一点(当时不存在,IIRC,这主要是假设的)。所以现实是,截至 2012 年,没有理由不明确定义行为,事实上,C++11 对这些情况进行了明确定义。

于 2012-09-24T20:47:47.427 回答
3

从 C++ 的角度来看,我认为答案非常简单:它是未定义的行为,因为 C 很久以前就将其变成了未定义的行为,而改变它基本上没有潜在的收益。

这指向了我猜测的更多预期问题:为什么 C 会做出这种未定义的行为?

我认为这没有那么简单的答案。一种可能性是简单的谨慎——知道在编写 C 标准时,C 已经在许多机器上实现、部署和使用。当时相当多的机器看起来像是很多我仍然看到的代码:最初只是作为个人实验设计的东西,它运行得很好,最终被指定为“生产”,甚至没有象征性地尝试修复任何东西。最严重的问题。因此,即使没有人知道这会破坏硬件,也没有人能真正确定这样的硬件也不存在,所以最安全的做法是称它为 UB 并完成它。

另一种可能性是它有点超出了简单的谨慎。尽管我们可以对现代硬件感到相当安全,但当时可能已经存在人们真正知道会在这方面存在重大问题的硬件,并且(特别是如果与该硬件相关的供应商在委员会中有代表)允许 C 运行硬件被认为很重要。

还有一种可能性是,即使没有人知道(甚至担心可能)某些现有实现可能会破坏,但他们预见到它会破坏某些东西的未来可能性,因此未定义的行为被视为未来证明的一种方式语言至少在一定程度上是有限的。

最后一种可能性是,编写该部分标准的人在提出一套似乎可以接受的规则后立即转向其他事情即使他们本可以提出至少一些人可能喜欢的其他规则更好的。

如果我不得不猜测,我会说这可能是我给出的第三种和第四种可能性的组合——委员会意识到并行计算的发展,但不知道它最终会如何运作,所以无论是谁写这篇文章时,最大化实施部分的自由度似乎是获得共识的最简单/最简单的途径,这样他们就可以完成它并继续做更大更好的事情。

于 2012-09-24T21:53:45.573 回答
2

未定义行为和未指定行为之间存在巨大差异。未指定的行为是格式良好的(即合法的),但该标准给编译器供应商留下了一些实现的自由度。未定义的行为是一种看起来在语法上正确的暴行。将行为视为“未定义”而不是完全非法(编译器必须拒绝)的主要原因是有时这种未定义的行为可能很难诊断。

于 2012-09-24T20:59:46.177 回答
0
a = foo(bar(1), bar(2)); // this is unspecified behaviour

这两个函数调用可以按任何顺序进行,但它们仍然是两个不同的函数调用。即使调用是内联的,机器指令也不允许重叠。实际上,它们确实有很多重叠,但是优化器被限制为生成严格地表现得好像函数调用是分开的代码。

a = i + i++; // this is undefined behaviour

使用标量 i,不需要分离:从 i 获取、添加和后增量的 cpu 指令可以自由混合,并且允许优化器假装它不知道左侧的 i 和右侧的 i权利是一样的。当违反此前提条件时,不知道它会产生什么样的损坏组件。因此,未定义。

于 2012-09-24T20:58:47.253 回答
0

MIPS 1 是一个带有加载延迟槽的合理实现。执行加载不会是即时的。结果仅在下一条指令开始后可见。对于编译器来说,这没什么大不了的。只需将不相关的指令放在下一个插槽中即可。

当然,编译器必须知道“无关”是什么。由于 C 规则禁止同时修改单个变量,编译器在查找必须不相关的指令方面有更多选择。如果两个操作出现在一个语句中,它们必须对不同的变量进行操作,因此是不相关的。

于 2012-09-25T08:44:45.137 回答