首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C++中的不确定行为是什么?它与未定义的行为有何不同?

C++中的不确定行为是什么?它与未定义的行为有何不同?
EN

Stack Overflow用户
提问于 2012-06-28 08:07:17
回答 3查看 3.8K关注 0票数 23

不确定的行为和未定义的行为在C++中有什么区别?这种分类对C代码也有效吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-07-06 20:09:17

编辑1: C11和C++11的最后草稿可以在网上找到:C11草案N1570C++11草案n3242,如果您没有最终标准的副本和它们的样子。(对文本外观和一些措辞/语法编辑做了其他调整。)

编辑2:将所有出现的“行为”修正为“行为”,以符合标准。

搜索C++11和C11标准时,不存在不确定规则或未定义规则的匹配。有不确定的值、不确定的顺序、不确定的未初始化等术语。

如果在Norman的回答中谈到陷阱和例外似乎很奇怪,那么要知道这些术语确实反映了第3节( in C11 standard )中的相关定义。

C++依赖于C的定义。关于行为类型的许多有用的定义可以在C11的第3节(在C11中)找到。例如,不定值在3.19.2中定义。请注意,C11的第2节(规范参考资料)为其他术语解释提供了其他来源,第4节定义了由于不遵守标准而发生未定义行为的情况。

C11的3.4节定义了行为,3.4.1定义了实现定义的行为,3.4.2定义了特定于地区的行为,3.4.3定义了未定义的行为,3.4.4定义了未指定的行为。对于值(第3.19节),有实现定义的值、不定值和未指定的值。

粗略地说,术语indeterminate指的是一种未指定/未知的状态,它本身不会导致未定义的行为。例如,此C++代码涉及一个不确定值:{ int = x;}。(这实际上是C++11标准中的一个例子。)这里,x首先被定义为一个整数,但此时它没有一个定义良好的值--然后它被初始化为它所拥有的任何(不确定/未知)值!

众所周知的术语未定义行为在C11中定义为3.4.3,它指的是

不可移植的或错误的程序结构或错误的数据,本国际标准对此没有任何要求

换句话说,未定义的行为是一些错误(在逻辑或状态中),接下来发生的事情都是未知的!因此,我们可以制定一个未定义的行为规则,即:在编写C/C++代码时避免未定义的行为!:-)

不确定行为规则将声明:除非需要,而且不影响程序的正确性或可移植性,否则避免编写不确定的代码。因此,与未定义的行为不同,不确定的行为并不一定意味着代码/数据是错误的,但是,它的后续使用可能是错误的,也可能不是错误的--因此需要注意确保程序的正确性。

不确定顺序等其他术语在正文中(例如,C11 5.1.2.3,第3段;C++11,第1.9节,第13段;即intro.executation)。(正如您可能猜到的,它指的是一个未指定的操作步骤顺序。)

海事组织如果对所有这些细微差别感兴趣,就必须同时获得C++11和C11标准。这将允许人们探索到定义等所需的详细程度。如果您没有这样的链接,这里提供的链接将帮助您探索最近发布的C11和C++11标准草案。

票数 7
EN

Stack Overflow用户

发布于 2012-06-28 09:00:18

下面的注释是基于C标准ISO-9899,而不是C++标准,但含义基本相同(参见C标准的第3.4和第4节;另见C++标准,ISO-14882,第1.3节;后一份文档并没有这样定义“未指定的值”,但后来确实使用了这个短语,并具有明显的含义)。官方标准文件并不是免费的(的确,它们很昂贵),但是上面的链接是指向委员会页面的,并包含了标准的免费“草稿”,你可以认为这基本上等同于最终的标准文本。

这些术语描述了模糊的阶梯。

所以往下走..。

大多数情况下,标准定义了在特定情况下应该发生什么:如果您编写了c=a+ba以及bint,那么c就是它们的总和(模块化一些细节)。当然,这就是标准的要点。

实现定义的行为是指标准列出了在特定情况下允许发生的两件或两件以上的事情;它没有规定哪一件是首选的,而是要求实现(解析C的实际编译器)在备选方案中做出选择,始终如一地执行相同的事情,并且实现必须记录它所做的选择。例如,单个文件是否可以由多个进程打开是由实现定义的。

未指定的行为是指标准列出了几个备选方案,因此每个选项都符合标准,但没有更进一步。一个实现必须在特定的情况下选择一个可供选择的选项,但不必每次都做同样的事情,并且不必在文档中承诺它将做出的选择。例如,未指定struct中的填充位。

不明确的行为是最极端的情况。这里,所有的赌注都取消了。如果编译器或它生成的程序遇到了未定义的行为,它可以做任何事情:它可以置乱内存、破坏堆栈、HCF,或者,在标准的极端情况下,会导致恶魔从你的鼻子里飞出来。但大多数情况下它会崩溃。所有这些行为都符合标准。例如,如果一个变量在同一个作用域中同时声明为static int i;int i;,或者如果您编写了#include <'my file'.h>,则效果是未定义的。

“值”有类似的定义。

未指定的值是有效值,但标准没有说明它是什么。因此,标准可能会说给定的函数返回一个未指定的值。您可以存储该值,如果您愿意,可以查看它,而不会导致错误,但它并不意味着什么,而且函数下一次可能返回一个不同的值,这取决于月亮的相位。

实现定义的值就像实现定义的行为。与未指定的值一样,它是一个有效值,但是实现的文档必须提交将返回的内容,并且每次都执行相同的操作。

未指定的值比未指定的值更不确定的值。它要么是一个未指定的值,要么是一个陷阱表示。陷阱表示是标准--表示某种神奇的值,如果您试图将其分配给任何东西,则会导致未定义的行为。这不一定是一个实际值;考虑它的最好方法可能是“如果C有异常,陷阱表示将是一个例外”。例如,如果在没有初始化的情况下在块中声明int i;,变量i的初始值是不确定的,这意味着如果在初始化变量i之前将其赋值给其他对象,则行为是未定义的,编译器有权尝试所述的“越界”技巧。当然,在大多数情况下,编译器会做一些不那么引人注目/有趣的事情,比如将其初始化为0或其他一些随机有效值,但是不管它做了什么,您都无权使用object。

所有这些不精确之处在于给编译器作者最大的自由。这对编译器编写人员来说是件好事(这也是让C编译器在如此广泛的平台上运行相当容易的原因之一),但对于贫穷的用户来说,这确实让事情变得更有趣而不是有趣。

编辑1:澄清不确定值。

编辑2:包含到C++标准的链接,并注意委员会草案基本上等同于最终标准,但是是免费的。

票数 39
EN

Stack Overflow用户

发布于 2012-06-28 08:18:24

我认为标准提到了未定义的行为和不确定的价值。所以,一个是关于行为的,另一个是关于价值观的。

这两者都是正交的,例如,在存在不定值的情况下,行为仍然可以很好地定义。

票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11240484

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档