0

C中未初始化数组的结果来自哪里?它们是随机分配的值还是只是存储在内存中的先前值?

#include <stdio.h>

int main (void)
{
    int values[10];
    int index; 

    values[0] = 197;
    values[2] = -100;
    values[5] = 350;
    values[3] = values[0] + values[5];
    values[9] = values[5] / 10;
    --values[2];

    for ( index = 0; index < 10; index++ )
        printf ("values[%i] = %i\n", index, values[index]);

    return 0; 
}

和输出:

$ ./a.exe
values[0] = 197
values[1] = 0
values[2] = -101
values[3] = 547
values[4] = 8
values[5] = 350
values[6] = 51
values[7] = 0
values[8] = 44045216
values[9] = 35
4

4 回答 4

2

章节和诗句

6.2.4 对象的存储持续时间
...
5 其标识符声明为没有链接且没有存储类说明符的对象static具有自动存储持续时间,某些复合文字也是如此。尝试从与对象关联的线程以外的线程间接访问具有自动存储持续时间的对象的结果是实现定义的。

6 对于这样一个没有可变长度数组类型的对象,它的生命周期从进入与其关联的块开始,直到该块的执行以任何方式结束。(进入封闭的块或调用函数会暂停,但不会结束当前块的执行。)如果递归地进入块,则每次都会创建对象的新实例。对象的初始值是不确定的。如果为对象指定了初始化,则在执行块时每次到达声明或复合文字时都会执行它;否则,每次达到声明时,该值变得不确定。

重点补充。

基本上,具有auto存储持续时间的对象不会隐式初始化为任何特定值 - 它们具有最后写入该特定内存位置1的值。您不能依赖该值为 0(或其他任何值)。

上面引用的最后一句话适用于这样的情况:

for (;;)
{
  int x;
  do_something_with( x );
}

循环的每次迭代都会有效地破坏和重新创建x,并且您不能依赖在x循环的任何迭代中写入的值将被传递到下一次迭代。 实际上,在类似 x86 的系统上,它很可能会被继承,但不要假设到处都是这种情况。

请注意,在以调试模式或其他方式构建时,实现可能会决定auto使用某个已知值初始化变量。


  1. 其中的机制是广泛而多样的,不值得在这里讨论。

于 2018-04-05T20:03:31.820 回答
1

您认为“未初始化”是什么意思?

这意味着该值尚未设置。因为它还没有被设置,所以它可以有任何值存储在那里。

也许是 0,也许是 547……
任何值都是有效的,并且不能保证你会找到什么。

于 2018-04-05T16:47:33.083 回答
1

未初始化的值只是您的应用程序尚未写入的内存地址。这就像拥有一个您周围的每个人都使用的记事本。当您的程序运行时,它会获得该记事本的一小部分,以前可能会或可能不会被其他人使用过。如果它是(很可能),那么它仍然会写一些东西,但可能对你没有任何意义。如果你想知道那里有什么,你必须写一些东西。一般来说,我们会向它写入 0,这就像从空纸开始擦除所有内容一样。

于 2018-04-05T16:55:19.477 回答
0

嗯,这就是 C 编程 101。C 是一种面向过程的语言,并没有实现面向对象语言(如 Java)中存在的某些特性,例如“自动”和保证变量的初始化。

如果您在 C 中声明一个自动变量(在堆栈上不是动态分配的)并且不提供初始值,那么该变量将具有我们所说的“垃圾值”。这是一般行为,但具体实现可能会有所不同。

让我举个例子吧:

int a;  //a variable with no initial value
printf("%d", a); 

我们无法预测这将打印什么。可能是 0,也可能是其他任何值。该程序也可能崩溃。本质上,这是未定义的行为。

如果在 Java 中也这样做,那么肯定会打印 0(因为 Java 默认将所有整数初始化为 0)。

现在来到您的数组问题:这是单个整数还是整数数组都没有关系。您未明确分配值的任何内存位置都将具有“垃圾值”。它可以是 0 或其他值。此行为完全依赖于机器且不可预测。

底线是:确保变量在使用前被初始化。

于 2018-04-05T16:51:07.130 回答