未定义与未指定与实现定义的行为

Undefined vs. Unspecified vs. Implementation-defined behavior

本文关键字:实现 未指定 未定义 定义      更新时间:2023-10-16

维基百科有关于未定义和未指定行为的页面,并且指向它们的链接在SO的评论和答案中大量使用。

每个都以一个注释开头,不要与其他注释混淆,但除了一个没有非常明确的句子外,他们没有指出它们之间的区别。

其中一个给出了一个例子(比较 2 个变量的地址:&a < &b),并评论说这将导致C++ 中未指定的行为,在 C 中未定义

是否有可能以清晰易懂的方式查明未定义未指定行为之间的实质性区别

简而言之:

  • 未定义的行为:这是不行的
  • 未指定的行为:这是可以的,但结果可能是任何东西*
  • 实现定义的行为:这是可以的,结果可能是任何东西*,但编译器手册应该告诉你

或者,引用C++标准(N4659 第 3 节,术语和定义):

3.28 未定义的行为:本国际标准未提出要求的行为

3.29 未指定行为:行为,对于格式良好的程序构造和正确的数据,取决于实现

3.12 实现定义的行为:行为,对于格式良好的程序构造和正确的数据,这取决于实现和 每个实施文档

>EDIT:*正如M.M在评论中指出的那样,说未指明的行为的结果可能是任何事情,这并不完全正确。事实上,正如标准本身在第3.29段的说明中所指出的那样

可能的行为范围通常由本国际标准划定。

因此,在实践中,您对可能的结果有一些想法,但究竟会发生什么取决于您的编译器/编译器标志/平台/等。

未指定及其示例( &a < &b )似乎说编译器编写者不必承诺它在堆栈上存储变量的位置,并且如果添加或删除附近的项目(不更改 a 和 b 的声明顺序),结果可能会改变。

特定于实现的项目是诸如a % b之类的项目,其中结果由实现自行决定(通常基于硬件),当 a 为负时会发生什么。

在这里,描述将会发生什么很重要,但如果标准致力于特定行为,则会影响性能。

未定义的行为描述了程序变得格式不正确的点 - 它可能在特定平台上工作,但没有任何充分的理由。