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