不确定行为与C ++中的未定义行为有什么区别?此分类是否也适用于C代码?
答案 0 :(得分:36)
以下评论基于C标准ISO-9899,而不是C ++标准,但其含义基本相同(参见C标准的3.4和4节;另见C ++标准,{ {3}},第1.3节;后一个文件没有定义'未指定的值',但后来确实使用了该词组具有明显的含义)。官方标准文件不是免费的(事实上,它们很昂贵),但上面的链接是委员会页面,并包括标准的免费“草稿”,您可以将其视为与最终标准文本基本相同。 / p>
这些术语描述了模糊的阶梯。
所以,向下走......
大多数情况下,标准定义了在特定情况下应该发生的事情:如果你写c=a+b
而a
和b
是int
,那么{{1是他们的总和(模数一些细节)。当然,这是标准的要点。
实现定义的行为是标准列出在特定情况下允许发生的两件或更多事情的地方;它没有规定哪一个是首选的,但是 要求实现(解析C的实际编译器)在备选方案之间作出选择,同样地做同样的事情,并且实现< em>必须记录它做出的选择。例如,是否可以通过多个进程打开单个文件是实现定义的。
未指定的行为是标准列出几个备选方案的地方,因此每个备选方案都符合标准,但不再进一步。实现必须选择其中一个替代方案来选择特定情况,但不必每次都做同样的事情,并且不必在文档中提交它将做出哪些选择。例如,c
中的填充位未指定。
未定义的行为是最极端的情况。所有的赌注都关闭了。如果编译器或它生成的程序遇到未定义的行为,它可以执行任何操作:它可以扰乱内存,损坏堆栈,ISO-14882或者在标准极端情况下,导致恶魔飞出你的鼻子。但大多数情况下它只会崩溃。所有这些行为都符合标准。例如,如果在同一范围内同时声明变量struct
和static int i;
,或者您编写int i;
,则效果未定义。
“价值”有类似的定义。
未指定的值是有效值,但标准没有说明它是什么。因此,标准可能会说给定函数返回未指定的值。您可以存储该值并在需要时查看它,而不会导致错误,但这并不意味着什么,并且该函数可能会在下次返回不同的值,具体取决于月亮的相位。
实现定义的值与实现定义的行为类似。与未指定的一样,它是一个有效的值,但实现的文档必须在将返回的内容上提交,并且每次都执行相同的操作。
不确定值比未指定更加未指定。它可以是未指定的值,也可以是陷阱表示。陷阱表示是标准 - 代表一些神奇的价值,如果你试图将它分配给任何东西,会导致不确定的行为。这不一定是实际价值;可能最好的思考方式是“如果C有异常,陷阱表示将是一个例外”。例如,如果您在一个块中声明#include <'my file'.h>
而未进行初始化,则变量int i;
的初始值为 indeterminate ,这意味着如果您尝试将此值分配给某个在初始化之前,行为是未定义的,并且编译器有权尝试所述的恶魔欺骗技巧。当然,在大多数情况下,编译器会做一些不太戏剧性/有趣的事情,比如将其初始化为0或其他一些随机有效值,但无论它做什么,你都无权反对。
所有这些不精确的关键是为编译器编写者提供最大的自由度。这对编译器编写者来说很好(这也是让C编译器在如此大范围的平台上运行相当容易的原因之一),但它确实让穷人用户感到有趣而不是有趣。
修改1 :澄清不确定的值。
编辑2 :包含指向C ++标准的链接,并注意委员会草案基本上等同于最终标准,但是免费。
答案 1 :(得分:8)
我认为标准提到未定义的行为并且不确定值。所以一个是关于行为而另一个关于价值观。
这两个有点正交,例如,在存在不确定值的情况下仍然可以很好地定义行为。
答案 2 :(得分:7)
编辑1: C11和C ++ 11的最新草稿可在线获取:C11 draft N1570和C++11 draft n3242如果您没有最终版本的副本标准和美妙的东西。 (已完成对文本外观和一些措辞/语法编辑的其他调整。)
编辑2:将所有出现的“行为”修正为符合标准的“行为”。
搜索C ++ 11和C11标准时,不确定规则或未定义规则没有匹配项。有一些术语,如不确定值,不确定序列,不确定未初始化等。
如果在Norman Gray的回答中谈论陷阱和异常似乎很奇怪,请知道这些术语确实反映了 C11标准中第3节中的相关定义。
C ++依赖于C的定义。关于行为类型的许多有用定义可以在C11的第3节(在C11中)中找到。例如, indeterminate value 在3.19.2中定义。请注意,C11的第2节(规范性引用文件)提供了其他术语解释的其他来源,第4节定义了不符合的情况下未定义的行为等情况。标准。
C11的3.4节定义了行为,3.4.1定义了实现定义的行为,3.4.2定义了特定于语言环境的行为,3.4。 3定义了未定义的行为,3.4.4定义了未指定的行为。对于 value (第3.19节),有实现定义值,不确定值和未指定值。< / p>
简而言之,术语不确定是指未指定/未知状态,它本身不会导致未定义行为。例如,这个C ++代码涉及一个不确定的值:{int x = x; }。 (这实际上是C ++ 11标准中的一个例子。)这里x被定义为第一个整数,但此时它没有明确定义的值 - 然后它被初始化为任何(不确定/未知)它有价值!
众所周知的术语未定义的行为在C11的3.4.3中定义,并且指的是
的任何情况不可移植或错误的程序构造或错误数据,本国际标准不对其施加任何要求
换句话说,未定义的行为是一些错误(在逻辑或状态中),接下来发生的任何事情都是未知的!因此,可以制定一个未定义的[行为]规则,指出:在编写C / C ++代码时避免未定义的行为! : - )
不确定[行为]规则将指出:避免编写不确定代码,除非需要和它不会影响程序正确性或便携性。因此,与未定义的行为不同,不确定的行为并不一定暗示代码/数据是错误的,但是,其后续使用可能会或可能不会是错误的 - 所以需要小心确保保持计划的正确性。
不确定顺序等其他术语在正文中(例如,C11 5.1.2.3第3段; C ++ 11,第1.9节第13段;即[intro.executation]) 。 (正如您可能猜到的,它指的是未指定的操作步骤顺序。)
IMO如果对所有这些细微差别感兴趣,那么获得C ++ 11和C11标准是必须的。这将允许人们通过定义等探索所需的详细程度。如果您没有这样的链接,将帮助您使用上次发布的C11和C ++ 11标准草案进行探索。< / p>