当我在 C 中打印一个未初始化的变量时会发生什么?


What happens when I print an uninitialized variable in C++?

为什么会打印 32767 (或其他随机数)?什么是 std::cout 打印?为什么不是NULL(或0)?

1
2
3
4
5
int main()
{
    int a;
    std::cout << a;
}


这是因为具有自动存储持续时间的变量在 C 中不会自动初始化为零。在 C 中,您不需要为不需要的东西付费,并且自动初始化变量需要时间(将内存位置设置为零最终会减少为机器指令,然后将其转换为控制物理位)。

该变量被保留一个内存位置,并且碰巧在该内存位置有一些垃圾。 cout.

正在打印该垃圾

正如@dwcanillas 所指出的,这是未定义的行为。相关:C 中声明的、未初始化的变量会发生什么?它有价值吗?

来自 C 标准(强调我的):

8.5 初始化器 [dcl.init]

7) To default-initialize an object of type T means:

  • If T is a (possibly cv-qualified) class type (Clause 9), constructors are
    considered. The applicable constructors are enumerated (13.3.1.3), and the best
    one for the initializer () is chosen through overload resolution (13.3). The
    constructor thus selected is called, with an empty argument list, to initialize >> the object.
  • If T is an array type, each element is default-initialized.
  • Otherwise, no initialization is performed.

12) 如果没有为对象指定初始化器,则该对象是默认初始化的。当获得具有自动或动态存储持续时间的对象的存储时,该对象具有不确定的值,如果没有对该对象执行初始化,则该对象将保留一个不确定的值,直到该值被替换(5.18)。 [注意:具有静态或线程存储持续时间的对象是零初始化的,请参见 3.6.2。 — 尾注 ] 如果评估产生不确定的值,则行为未定义,但以下情况除外:

— If an indeterminate value of unsigned narrow character type (3.9.1) is produced by the evaluation of:

— the second or third operand of a conditional expression (5.16),

— the right operand of a comma expression (5.19),

— the operand of a cast or conversion to an unsigned narrow character type (4.7, 5.2.3, 5.2.9, 5.4), or

— a discarded-value expression (Clause 5)

...


这是未定义的行为。您正在打印占用 a 内存的任何内容,在这种情况下恰好是 32767.


C 14 (N3936) [dcl.init]/12 涵盖了该行为:

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.

[...] If an indeterminate value is produced by an evaluation, the behavior is undefined except in the following cases:

并且您的代码未包含在任何"以下情况"中,这些情况涵盖了允许传播 unsigned char 不确定值的几种情况。


因为 "a" 不是全局/静态的。它是一个自动变量,在运行时进行初始化。如果它是全局的,则初始化为零将在编译时发生。即

?静态变量在编译时初始化,因为它们的地址是已知且固定的。将它们初始化为 0 不会产生运行时成本。

?自动变量对于不同的调用可以有不同的地址,并且每次调用函数时都必须在运行时进行初始化,从而产生可能不需要的运行时成本。如果您确实需要该初始化,请请求它。