“IB”和“UB”是什么意思?

我已经多次使用过术语“IB”和“UB”,特别是在C ++的情况下。 我试着用Googlesearch,但显然这些双字母组合看到了很多用途。 :P

所以,我问你…当他们被认为是坏事时,他们是什么意思?

IB:实现定义的行为。 该标准将其留给特定的编译器/平台来定义精确的行为,但要求对其进行定义。

使用实现定义的行为可能是有用的,但使您的代码更轻便。

UB:未定义的行为。 该标准没有规定调用未定义行为的程序应如何行为。 也被称为“鼻恶魔”,因为理论上它可以使恶魔飞出你的鼻子。

使用未定义的行为几乎总是一个坏主意。 即使有时似乎有效,对环境,编译器或平台的任何改变都会随机破坏你的代码。

实现定义的行为和未定义的行为

C ++标准对于各种结构的影响是非常具体的,特别是你应该始终注意到这些types的问题

  • 未定义的行为意味着绝对没有保证。 该代码可以工作,或者它可以放火给你的硬盘或使恶魔飞出你的鼻子 。 就C ++语言而言,绝对可能发生任何事情。 实际上,这通常意味着你有一个不可恢复的错误。 如果发生这种情况,你不能真正相信你的应用程序的任何东西 (因为这种未定义的行为的影响之一可能只是弄乱了你的应用程序的其余部分使用的内存)。 不需要一致,所以两次运行程序可能会产生不同的结果。 它可能取决于月亮的阶段,你穿的衬衫的颜色,或绝对的其他东西。

  • 未指定的行为意味着程序必须做一些理智而一致的事情,但不需要certificate这一点。

  • 实现定义的行为与未指定的类似,但也必须由编译器编写者logging。 一个例子是reinterpret_cast的结果。 通常 ,它只是改变指针的types,而不修改地址,但映射实际上是实现定义的,所以编译器可以映射到一个完全不同的地址,只要它logging了这个select。 另一个例子是int的大小。 C ++标准不关心它是2,4或8字节,但它必须由编译器logging

但通常所有这些都是他们最好的避免。 在可能的情况下,坚持C ++标准本身规定的行为。 这样,你保证了可移植性。

您经常不得不依赖一些实现定义的行为。 这可能是不可避免的,但你仍然应该注意它,并且要注意你依赖于不同编译器之间可能会改变的东西。

另一方面,不确定的行为总是应该避免的。 一般来说,你应该假设它使你的程序以某种方式爆炸。

  • IB:是实现定义的行为 – 编译器必须logging它做了什么。 以负值执行>>操作就是一个例子。

  • UB:未定义的行为 – 编译器可以做任何事情,包括简单地崩溃或给出不可预知的结果。 解引用一个空指针属于这个类别,但是还有一些微妙的东西,例如指针算术,落在数组对象的范围之外。

另一个相关的术语是“不明确的行为”。 这是实现定义和未定义行为之间的一种。 对于未指定的行为,编译器必须根据标准做一些事情,但标准给出的select是由编译器决定的,不需要定义(甚至不一致)。 像子expression式的评价顺序就属于这个范畴。 编译器可以按照喜欢的顺序执行这些操作,并且可以在不同的版本中甚至在同一个版本的不同运行中以不同的方式执行(不太可能,但允许)。

UB: 未定义的行为

IB: 实施定义的行为

简短版本:

实现定义的行为(IB):正确编程但不确定*

未定义行为(UB):错误编程(即错误 !)

*)就语言标准而言“不确定”,当然在任何固定平台上都是确定的。