未初始化变量的后果:int vs unsigned char

msc*_*msc 25 c++ initialization undefined-behavior language-lawyer

我在cppreference.com上看到了以下示例

int x;     // OK: the value of x is indeterminate
int y = x; // undefined behavior
Run Code Online (Sandbox Code Playgroud)

这里int y = x;未定义的行为,因为它x是未初始化的.

但,

unsigned char c;     // OK: the value of c is indeterminate
unsigned char d = c; // OK: the value of d is indeterminate
Run Code Online (Sandbox Code Playgroud)

这里unsigned char d = c;不确定的行为,但unsigned char c;也是一个未初始化的变量.

那么,为什么unsigned char d不确定的价值呢?

bol*_*lov 26

cppreference.com这样的在线参考资料非常重要.但众所周知,有时错误或误解偶尔会漏掉.因此,在处理这些奇怪的事情时,转到官方C++标准总是一件好事.

N3936

§8.5初始化器[dcl.init]

12 [...]当获得具有自动或动态存储持续时间的对象的存储时,该对象具有不确定的值,并且如果没有对该对象执行初始化,则该对象保留不确定的值,直到该值被替换为止(5.17) ).[...]如果评估产生不确定的值,则行为未定义,但以下情况除外:

  • 如果通过评估产生无符号窄字符类型(3.9.1)的不确定值

    • [...]

    • 转换的操作数或转换为无符号窄字符类型(4.7,5.2.3,5.2.9,5.4)

    • [...]

    那么操作的结果就是一个不确定的值.

  • 如果通过评估一个简单赋值运算符(5.17)的右操作数产生无符号窄字符类型的不确定值,该操作数的第一个操作数是无符号窄字符类型的左值,则不确定值将替换所引用的对象的值.左操作数

  • 如果在初始化无符号窄字符类型的对象时通过初始化表达式的求值产生无符号窄字符类型的不确定值,则该对象被初始化为不确定的值.

例:

int f(bool b) {
  unsigned char c;
  unsigned char d = c; // OK, d has an indeterminate value
  int e = d; // undefined behavior
  return b ? d : 0; // undefined behavior if b is true
}
Run Code Online (Sandbox Code Playgroud)

所以(令我惊讶的是)标准支持了这一点.

至于为什么,最可能的原因也可以在标准中找到:

§3.9.1基本类型[basic.fundamental]

1 [...]对于无符号窄字符类型,值表示的所有可能位模式表示数字.这些要求不适用于其他类型


作为旁注,我才意识到这可以被邪恶的采访者使用:

问:您是否可以在明确定义的行为中将对象的有效值更改为未确定的值?如果有,怎么样?

一个.

unsigned char ind;
unsigned char x = 24;
x = ind; // x had a valid value, now x has an indetermined value
Run Code Online (Sandbox Code Playgroud)

  • @bolov这个虚构平台的名字是Itanium.Raymond Chen有一篇博客文章["ia64上未初始化的垃圾可能致命"](https://blogs.msdn.microsoft.com/oldnewthing/20040119-00/?p=41003/) (4认同)
  • 可能需要注意的是,您引用的子句仅适用于 C++14 及更高版本。在此之前,访问未初始化的“unsigned char”的值在形式上是未定义的。 (2认同)

Jos*_*son 18

从您引用的页面:从不确定值分配是未定义的行为,除了

如果将无符号窄字符类型或std :: byte的不确定值分配给具有无符号窄字符类型或std :: byte的另一个变量(变量的值变为不确定,但行为未定义)

我相信这是因为默认初始化可以将任何位组合放入变量中,而标准保证无符号窄字符类型可以采用由每个可能的位模式表示的值,对其他类型没有这样的保证.

  • 特别是这个参考; http://eel.is/c++draft/basic.fundamental#1 _对于无符号窄字符类型,值表示的每个可能位模式表示不同的数字.这些要求不适用于其他类型._ (5认同)