未定义与未指定与实现定义的行为
Undefined vs. Unspecified vs. Implementation-defined behavior
维基百科有关于未定义和未指定行为的页面,并且指向它们的链接在SO的评论和答案中大量使用。
每个都以一个注释开头,不要与其他注释混淆,但除了一个没有非常明确的句子外,他们没有指出它们之间的区别。
其中一个给出了一个例子(比较 2 个变量的地址:&a < &b
),并评论说这将导致C++ 中未指定的行为,在 C 中未定义。
是否有可能以清晰易懂的方式查明未定义和未指定行为之间的实质性区别?
简而言之:
- 未定义的行为:这是不行的
- 未指定的行为:这是可以的,但结果可能是任何东西*
- 实现定义的行为:这是可以的,结果可能是任何东西*,但编译器手册应该告诉你
或者,引用C++标准(N4659 第 3 节,术语和定义):
>EDIT:*正如M.M在评论中指出的那样,说未指明的行为的结果可能是任何事情,这并不完全正确。事实上,正如标准本身在第3.29段的说明中所指出的那样3.28 未定义的行为:本国际标准未提出要求的行为
3.29 未指定行为:行为,对于格式良好的程序构造和正确的数据,取决于实现
3.12 实现定义的行为:行为,对于格式良好的程序构造和正确的数据,这取决于实现和 每个实施文档
可能的行为范围通常由本国际标准划定。
因此,在实践中,您对可能的结果有一些想法,但究竟会发生什么取决于您的编译器/编译器标志/平台/等。
未指定及其示例( &a < &b )
似乎说编译器编写者不必承诺它在堆栈上存储变量的位置,并且如果添加或删除附近的项目(不更改 a 和 b 的声明顺序),结果可能会改变。
特定于实现的项目是诸如a % b
之类的项目,其中结果由实现自行决定(通常基于硬件),当 a 为负时会发生什么。
在这里,描述将会发生什么很重要,但如果标准致力于特定行为,则会影响性能。
未定义的行为描述了程序变得格式不正确的点 - 它可能在特定平台上工作,但没有任何充分的理由。
相关文章:
- 从 XML 中读取未指定结构的每个数据成员
- 用数据填充未指定大小的数组
- 访问从联合与另一个成员集复制的联合中的一个成员是否未定义或未指定?
- 在头文件中使用opencv类型来实现未定义的标识符
- 双循环变量的相等条件:未指定还是未定义
- SQL Server-未找到数据源名称,也未指定默认驱动程序
- 无法创建长度未指定
- 在Visual Studio中更新Qt翻译(.ts文件)时出现未指定错误
- 是否未指定在未评估的上下文中实例化模板/lambda
- 未定义与未指定与实现定义的行为
- 在 c++ 中获取未指定数量的输入
- 摆动,传递未指定维度的阵列
- 在尝试提交作业警告时,我一直在警告:与未指定行为的字符串字面结果比较[-WADDRESS]
- 我的基本C 程序中有一个未指定的错误
- OPENCV错误:未指定的错误(未实现该函数)
- 函数参数中数组大小未指定
- 从源代码编译 openCV:*** 未指定目标,也未找到生成文件.停
- 超载构造函数中的未指定字段
- CPack NSIS 组件未指定
- 未指定文件