Warm tip: This article is reproduced from serverfault.com, please click

c++-未定义,未指定和实现定义的行为

(c++ - Undefined, unspecified and implementation-defined behavior)

发布于 2010-03-07 21:10:30

什么是C和C ++中的未定义行为?未指定的行为和实现定义的行为呢?它们之间有什么区别?

Questioner
Zolomon
Viewed
11
2020-06-20 17:12:55

未定义的行为是C和C ++语言的那些方面之一,对于其他语言的程序员来说可能会感到惊讶(其他语言想更好地隐藏它)。基本上,即使许多C ++编译器不会报告程序中的任何错误,也可以编写行为无法预测的C ++程序!

让我们看一个经典的例子:

#include <iostream>

int main()
{
    char* p = "hello!\n";   // yes I know, deprecated conversion
    p[0] = 'y';
    p[5] = 'w';
    std::cout << p;
}

变量p指向字符串文字"hello!\n",下面的两个赋值想修改该字符串文字。这个程序做什么?根据C ++标准的第2.14.5节第11段,它会调用未定义的行为

尝试修改字符串文字的效果是不确定的。

我听到有人在尖叫“但是,等等,我可以编译这个问题并获取输出yellow”或“你的意思是未定义的字符串文字存储在只读存储器中,因此第一次分配尝试会导致核心转储”。这正是未定义行为的问题。基本上,一旦你调用未定义的行为(甚至是鼻恶魔),该标准将允许发生任何事情。如果根据你的语言思维模式有“正确”的行为,则该模式完全是错误的。C ++标准具有唯一的投票期限。

未定义行为的其他示例包括访问数组之外​​的数组,取消引用空指针,在对象生命周期结束后访问对象或编写所谓的聪明表达式(如)i++ + ++i

C ++标准的1.9节还提到了未定义行为的两个不太危险的兄弟,即未指定行为实现定义的行为

本国际标准中的语义描述定义了参数化的不确定性抽象机器。

抽象机的某些方面和操作在此国际标准中描述为实现定义的(例如sizeof(int))。这些构成了抽象机的参数。每个实现都应包括描述其在这些方面的特性和行为的文档。

抽象机的某些其他方面和操作在本国际标准中描述为未指定(例如,对函数自变量的求值顺序)。在可能的情况下,本国际标准定义了一组允许的行为。这些定义了抽象机的不确定性方面。

在本国际标准中,某些其他操作被描述为未定义(例如,取消引用空指针的效果)。[注意本国际标准对包含未定义行为的程序的行为不加任何要求。尾注]

具体而言,第1.3.24节规定:

允许的未定义行为的范围从完全忽略具有不可预测结果的情况到在翻译或程序执行过程中以环境特征的书面方式记录的行为(带有或不带有诊断消息)到终止翻译或执行(带有发布)诊断消息)。

你应该怎么做才能避免遇到未定义的行为?基本上,你必须阅读知道他们在说什么的作者的优秀C ++书籍螺丝互联网教程。螺丝废话。