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

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

>强>未定义行为>/E>是C语言和C++语言的一个方面,对来自其他语言的程序员来说是令人惊讶的(其他语言试图更好地隐藏它)。基本上,可以编写C++程序,这些程序不可预测地运行,即使许多C++编译器不会报告程序中的任何错误!p>

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

#包括&lt;iostream&gt;
int main()
{
char*p=&quot;hello!\n&quot;//是的,我知道,不推荐的转换
p[0]=“y”;
p[5]=‘w’;
标准::cout&lt;&lt;p;
}

变量p指向字符串literal&quot;你好!\",下面的两个赋值尝试修改该字符串文字。这个程序做什么?根据C++标准第2.14节第11段,调用未定义行为

试图修改字符串文字的效果未定义

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

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

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

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

本国际标准将抽象机的某些方面和操作描述为实现定义的(例如,sizeof(int))。这些构成了抽象机器的参数。每个实施应包括描述其在这些方面的特征和行为的文件

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

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

具体而言,第1.3.24节规定:

允许的未定义行为范围从完全忽略具有不可预测结果的情况,到在翻译或程序执行过程中以环境特有的文件化方式(无论是否发出诊断消息)进行行为,再到终止翻译或执行(发出诊断信息)

你能做些什么来避免陷入未定义的行为?基本上,你必须阅读那些知道他们在说什么的优秀的C++书籍。避免网络教程。避免Bull ScLydt。

发表评论