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

发布于 2024-10-04 09:48:42 字数 1064 浏览 2 评论 0 原文

这个问题出现在问题答案的评论中 当类型转换为 int 时,C/C++ bool 类型是否始终保证为 0 或 1?

相关代码分配一个 < 的(本地)数组code>bool 而不初始化它们的值。

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

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

一些评论者认为读取例如 b[0] 是未定义的行为。 C++ 标准中是否有这样的规定?我仍然相信相反的情况:

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

  2. 该行为在 C 中确实未定义:C 中声明的、未初始化的变量会发生什么?它有价值吗?并且一些受访者似乎混淆了两者。

  3. 在最新的 C++0x 草案中,我找不到不确定值的定义,尤其是没有允许访问此类值来触发处理器陷阱的定义。事实上,Bjarne Stroustrup 不确定不确定值可能是什么:http: //zamanbakshifirst.blogspot.com/2007/02/c-independent-value.html

The question arose in the comments of an answer to the question Is C/C++ bool type always guaranteed to be 0 or 1 when typecast'ed to int?

The code in question allocates a (local) array of bool without initializing their value.

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

Clearly the values in b are indeterminate.

Some of the commenters opined that reading e.g. b[0] was undefined behavior. Is this stated anywhere in the C++ standard? I am still convinced of the opposite:

  1. There is clearly storage allocated and initialization of the fundamental bool type is complete, since it doesn't have a constructor. It is thus certainly not the same as dereferencing an uninitialized pointer, or calling methods/cast operators on uninitialized non-trivial objects. These specific cases seem to be covered by the standard.

  2. The behavior is indeed undefined in C: What happens to a declared, uninitialized variable in C? Does it have a value? and some respondents seem to confuse the two.

  3. In the latest C++0x draft I can find no definition of indeterminate value especially no definition that would allow accessing such a value to trigger a processor trap. Indeed, Bjarne Stroustrup is not sure what an inderminate value may be: http://zamanbakshifirst.blogspot.com/2007/02/c-indeterminate-value.html

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

他夏了夏天 2024-10-11 09:48:42

是的,形式上不确定值的右值转换是 UB (除了 unsigned char ,最初我写的是“和变体”,但我记得形式迎合 1 的补码有符号字符,其中可能可以使用负 0作为陷阱值)

我懒得为你做标准段落查找,也懒得关心对此的否决票,

但是,实际上只有(1)过时的架构,也许(2)64位上的问题系统。

编辑:哎呀,我现在似乎想起了一篇关于访问不确定字符的正式 UB 的博客文章和相关缺陷报告。所以也许我必须实际检查标准,+搜索DR。啊,那得晚点了,现在喝咖啡!

编辑2:Johannes Schaub很友善地提供了这个链接到SO问题,其中讨论了访问char的UB。所以,这就是我记得的地方!谢谢,约翰内斯。

干杯&呵呵,,

yes, formally an rvalue conversion of indeterminate value is UB (except for unsigned char, originally i wrote "and variants" but as i recall the formal caters to 1's complement signed char where possibly minus 0 could be used as trap value)

i'm too lazy to do the standard paragraph lookup for you, and also to lazy to care about downvotes for that

however, in practice only a problem on (1) archaic architectures, and perhaps (2) 64-bit systems.

EDIT: oops, i now seem to recall a blog posting and associated Defect Report about formal UB for accessing indeterminate char. so perhaps i'll have to actually check the standard, + search DRs. argh, it will have to be later then, now coffee!

EDIT2: Johannes Schaub was kind enough to provide this link to SO question where that UB for accessing char was discussed. So, that's where I remembered it from! Thanks, Johannes.

cheers & hth.,

澉约 2024-10-11 09:48:42

这个问题的答案随着最新的 C++1y 工作草案(N3946)而改变,我们可以在其中找到 此处8.5 Initializers 段落 12 与 C++03 和 C++11 相比发生了很大变化,现在包含以下内容(强调我的):

如果没有为对象指定初始值设定项,则该对象为
默认初始化。 当使用自动或
获得动态存储持续时间,该对象具有不确定的

value
,如果没有对该对象进行初始化,则
对象保留不确定的值,直到该值被替换
(5.17)。 [注意:具有静态或线程存储持续时间的对象是
零初始化,参见 3.6.2。 — 尾注] 如果不确定值是
由评估产生,行为是未定义的,除了
以下案例

并继续列出一些仅无符号窄字符类型的例外情况,我在C++1y 在使用不确定值和未定义行为方面是否发生了变化?

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

以前,我们需要使用左值到右值的转换来证明这是未定义的,但这是有问题的,因为 转换未指定

请注意,不确定值在本节中以斜体显示,因此这意味着它是就地定义的,因此现在 C++1y 实际上定义了该术语。以前,该术语在没有定义的情况下使用,这在 缺陷报告616

The answer to this question changes with the latest C++1y working draft(N3946) which we can find here. Section 8.5 Initializers paragraph 12 changes a lot from C++03 and C++11 and now contains the following (emphasis mine):

If no initializer is specified for an object, the object is
default-initialized. When storage for an object with automatic or
dynamic storage duration is obtained, the object has an
indeterminate
value
, and if no initialization is performed for the object, that
object retains an indeterminate value until that value is replaced
(5.17). [ Note: Objects with static or thread storage duration are
zero-initialized, see 3.6.2. — end note ] If an indeterminate value is
produced by an evaluation, the behavior is undefined except in the
following cases
:

and goes on to list some exceptions for unsigned narrow character type only, I have a complete quote in Has C++1y changed with respect to the use of indeterminate values and undefined behavior?.

So in your case b has automatic storage duration and is not initialized and therefore has indeterminate value. So evaluating b[0] is indeed undefined behavior.

Previously we were required to use the lvalue-to-rvalue conversion to prove this was undefined but that is problematic since the conversion is underspecified.

Note that indeterminate value is italicized in this section and therefore it means it is being defined in place and so now C++1y actually defines the term. Previously the term was used without a definition, this is covered in defect report 616.

抠脚大汉 2024-10-11 09:48:42

对于 bool,标准在 3.9.1 基本类型 下表示:

bool 类型的值为 true 或
错误。

脚注指出:

按照描述的方式使用布尔值
按照本国际标准
“未定义”,例如通过检查
未初始化的自动值
对象,可能会导致它的行为就像
这既不真实也不虚假。

On bool, the standard says under 3.9.1 Fundamental types:

Values of type bool are either true or
false.

With a footnote stating:

Using a bool value in ways described
by this International Standard as
“undefined,” such as by examining the
value of an uninitialized automatic
object, might cause it to behave as if
it is neither true nor false.

懒猫 2024-10-11 09:48:42

读取不确定值通常会导致未定义行为这一事实不仅仅是一个“理论”问题。即使对于所有可能的位模式都已定义值的类型,不确定值的行为方式与未指定值不同也不应被视为“令人惊讶”。例如,如果 *p 包含不确定值,并且 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 的值是不确定的,则不会禁止编译器
让两个“if”语句之间的代码修改其值。
例如,如果 *p 占用的存储空间被“float”占用
在释放和重新分配之前,编译器可能会写“float”
上面两个“if”语句之间的值。

The fact that reading an Indeterminate Value generally results in Undefined Behavior is not merely a "theoretical" issue. Even for types where all possible bit patterns have defined values, it should not be considered "surprising" for indeterminate values to behave in ways which differ from Unspecified values. For example, if *p holds Indeterminate Value, and x is not used anywhere except
as shown, the code:

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;

could be rewritten as:

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

If the value of *p is Indeterminate, a compiler would not be forbidden
from having the code between the two "if" statements modify its value.
For example, if the storage occupied by *p was occupied by a "float"
before it freed and re-malloc'ed, the compiler might write that "float"
value between the two "if" statements above.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文