我读了几个关于未定义行为和序列点的非常好的答案(例如未定义的行为和序列点),我明白了
int i = 1;
a = i + i++; //this is undefined behaviour
Run Code Online (Sandbox Code Playgroud)
根据C++标准,是未定义的代码.但是,未定义的行为背后的深层原因是什么?是否足以使其成为未指明的行为?正常的论点是,通过几个序列点,C++编译器可以更好地针对不同的体系结构进行优化,但是不会让它未指定允许这些优化吗?在
a = foo(bar(1), bar(2)); //this is unspecified behaviour
Run Code Online (Sandbox Code Playgroud)
编译器也可以优化,并且它不是未定义的行为.在第一个例子中,似乎很清楚,a是2或3,所以语义似乎对我来说很清楚.我希望有一个推理,为什么有些东西是未指定的,有些是未定义的.
并非所有这些优化.例如,Itanium可以并行执行添加和增量,并且可能会因为尝试执行此类操作而出现硬件异常.
但这是一个完全微观优化,编写编译器以利用这是非常困难的,并且它是一个非常罕见的架构,可以做到(当时没有,IIRC,它主要是假设的).所以现实情况是,截至2012年,没有理由不进行明确定义的行为,事实上,C++ 11更多地将这些情况定义得很明确.
从 C++ 的角度来看,我认为答案非常简单:它被设为未定义的行为,因为 C 很早之前就将其设为未定义的行为,并且从更改它本质上没有潜在的好处。
这指出了我猜想的问题:为什么 C 会做出这种未定义的行为?
我认为这没有那么简单的答案。一种可能性是简单的谨慎——知道在编写 C 标准时,C 已经在许多机器上实现、部署和使用。当时的相当多的机器看起来像很多我仍然看到的代码:最初只是作为个人实验而设计的东西,效果很好,最终被指定为“生产”,甚至没有象征性地尝试修复任何东西。最严重的问题。因此,即使没有人知道这种硬件会损坏,也没有人能真正确定这样的硬件不存在,所以最安全的方法就是将其称为 UB,然后就结束了。
另一种可能性是,它有点超出了简单的谨慎范围。尽管我们对现代硬件感到相当安全,但当时人们可能确实知道存在一些硬件会存在重大问题,并且(特别是如果与该硬件相关的供应商在委员会中有代表的话)允许 C 运行在该硬件被认为很重要。
另一种可能性是,尽管没有人知道(甚至担心这种可能性)某些现有的实现可能会被破坏,但他们预见到了未来某些东西会被破坏的可能性,因此未定义的行为被视为未来证明的一种方式。语言至少在一定程度上是有限的。
最后一种可能性是,无论是谁编写了这部分标准,只要他们提出了一套似乎可以接受的规则,他们就会立即转向其他事情,尽管他们本可以提出至少有些人可能会喜欢的其他规则更好的。
如果我不得不猜测,我会说这可能是我给出的第三种和第四种可能性的组合——委员会意识到并行计算的发展,但不知道它最终会如何运作,所以无论对谁来说写到这里,最大化实施方面的自由度似乎是获得共识的最简单/最简单的途径,这样他们就可以完成它并继续做更大更好的事情。
| 归档时间: |
|
| 查看次数: |
503 次 |
| 最近记录: |