读取不确定值的未定义行为?

时间:2010-11-25 16:47:45

标签: c++ initialization undefined-behavior

问题Is C/C++ bool type always guaranteed to be 0 or 1 when typecast'ed to int?

的答案评论中出现了问题

有问题的代码在不初始化值的情况下分配bool的(本地)数组。

const int n = 100;
bool b[n];

显然b中的值是不确定的。

一些意见提供者认为阅读,例如b[0]是未定义的行为。这是在C ++标准中的任何地方陈述的吗?我仍然相信相反:

  1. 显然存储已分配,并且基本bool类型的初始化已完成,因为它没有构造函数。因此,它肯定与取消引用未初始化的指针或在未初始化的非平凡对象上调用方法/强制转换操作符不同。标准似乎涵盖了这些具体案例。

  2. C:What happens to a declared, uninitialized variable in C? Does it have a value?中的行为确实未定义,而且一些受访者似乎对这两者感到困惑。

  3. 在最新的C ++ 0x草案中,我找不到 indeterminate value 的定义,特别是没有允许访问这样的值来触发处理器陷阱的定义。实际上,Bjarne Stroustrup不确定什么是inderminate值:http://zamanbakshifirst.blogspot.com/2007/02/c-indeterminate-value.html

4 个答案:

答案 0 :(得分:6)

这个问题的答案随最新的C ++ 1y工作草案(N3946)而变化,我们可以找到here。部分8.5 初始化程序 12 在C ++ 03和C ++ 11中发生了很大变化,现在包含以下内容(强调我的 >):

  

如果没有为对象指定初始化程序,则该对象为   默认初始化。 使用自动或自动存储对象时   获得动态存储持续时间,该对象具有 不确定   值,如果没有为对象执行初始化,那么   对象保留不确定的值,直到替换该值   (5.17)。 [注意:具有静态或线程存储持续时间的对象是   零初始化,见3.6.2。 - 结束注释] 如果是不确定的值   通过评估产生,行为是不确定的,除了在   以下案例

继续列出无符号窄字符类型的一些例外情况,我在Has C++1y changed with respect to the use of indeterminate values and undefined behavior?中有完整的引用。

因此,在您的情况下,b具有自动存储持续时间且未初始化,因此具有不确定的值。所以评估b[0]确实是未定义的行为。

之前我们需要使用左值到右值的转换来证明这是未定义的,但这是the conversion is underspecified以来的问题。

请注意,本节中的不确定值是斜体,因此它意味着它正在定义,因此现在C ++ 1y实际定义了该术语。以前使用的术语没有定义,defect report 616中包含了这一点。

答案 1 :(得分:4)

是的,正式地,不确定值的右值转换是UB(unsigned char除外,最初我写了“和变体”但是我记得正式迎合1的补码签名字符,其中可能减去0可以用作陷阱值)

我懒得为你做标准的段落查找,也懒得关心那个暗淡的回文

然而,实际上只有(1)古老架构和(2)64位系统存在问题。

编辑:oops,我现在好像回想起一篇关于正式UB访问不确定字符的博客文章和关联的缺陷报告。所以也许我必须实际检查标准,+搜索DR。唉,它必须晚些时候,现在咖啡!

EDIT2 :Johannes Schaub非常友好地提供了这个link to SO question,其中讨论了用于访问char的UB。所以,这就是我记得的地方!谢谢,约翰内斯。

欢呼&第h。,

答案 2 :(得分:3)

bool上,标准说明 3.9.1基本类型

  

bool类型的值为true或   假的。

用脚注说明:

  

以所述方式使用bool值   按此国际标准   “undefined”,等通过检查   未初始化的自动值   对象,可能会使其表现得像一样   它既不是真也不是假。

答案 3 :(得分:0)

阅读不确定值通常导致未定义行为的事实不仅仅是理论上的"问题。即使对于所有可能的位模式都有定义值的类型,也不应该考虑#34;令人惊讶的"对于不确定的值,其行为方式与Unspecified值不同。例如,如果* p包含Indeterminate Value,则除了以外的任何地方都不使用x 如图所示,代码:

uint32_t x,y,z;
...
x = *p;
if (condition1) y=x;
... code that "shouldn't" affect *p if its value is defined
if (condition2) z=x;

可以改写为:

if (condition1) y=*p;
... code that "shouldn't" affect *p if its value is defined
if (condition2) z=*p;

如果* p的值为Indeterminate,则不会禁止编译器 从两个&#34之间的代码;如果"语句修改其值。 例如,如果* p占用的存储空间被一个" float" 在它被释放并重新进行malloc编辑之前,编译器可能会写出" float" 两者之间的价值"如果"上述陈述。