在C语言中,声明但未初始化的变量会发生什么?它是否具有值?

17 浏览
0 Comments

在C语言中,声明但未初始化的变量会发生什么?它是否具有值?

如果在C中我写:

int num;

在我给num赋值之前,num的值是否不确定?

0
0 Comments

在C语言中,声明但未初始化的变量的值取决于变量的存储期。具有静态存储期的变量总是隐式地初始化为零。对于自动(局部)变量来说,未初始化的变量具有不确定的值。不确定的值意味着无论你在变量中“看到”的“值”是什么,它不仅是不可预测的,甚至不能保证是稳定的。例如,在实践中(忽略未定义行为),以下代码不保证变量a和b将接收相同的值。有趣的是,这不是一些学究理论的概念,这实际上是优化的结果。因此,一般来说,被广泛认同的答案“它被初始化为内存中的垃圾值”根本不正确。未初始化变量的行为与用垃圾值初始化的变量的行为不同。

0
0 Comments

在C中,声明但未初始化的变量的值取决于其存储类别。如果是静态或全局变量,它们将被置为零。如果是自动变量,其值是不确定的。

这一规定适用于C89、C99和C11标准。根据标准的规定,如果一个具有自动存储期的对象未显式初始化,则其值是不确定的;如果一个具有静态存储期的对象未显式初始化,则会根据其类型进行隐式初始化。

在实际应用中,每个堆栈页的初始值实际上都是零。但当程序访问任何自动存储类别的值时,它看到的是上一次使用这些堆栈地址时程序本身留下的值。如果分配了大量的自动数组,最终它们会以零开始。

对于“不确定”的确切含义,C89标准中没有明确规定,而C99标准指出,它可以是未指定的值或陷阱表示。

为什么会这样呢?一个不同的SO回答解释了这个问题。

总体而言,初始化为不确定值意味着它可以是任何值。它可以是零,也可以是之前存在的值,还可以导致程序崩溃,甚至可以使计算机从CD槽中产生蓝莓煎饼。在规范中,您没有任何保证。至少在规范中是这样的...任何实际执行类似操作的编译器都会受到严厉的反对。

至于静态变量的初始值是否总是取决于编译器或操作系统,答案是编译器承担着主要责任,它必须运行全球现有的C代码目录,并且其次要责任是符合标准。当然可以以不同的方式实现,但为什么要这么做呢?此外,对于静态数据来说,将其设置为不确定值是棘手的,因为出于安全原因,操作系统通常会首先将页面清零。(自动变量只是表面上不可预测,因为您自己的程序通常在较早的时候使用这些堆栈地址。)

需要注意的是,使用不确定值会导致未指定的行为,除了陷阱表示的情况外,并不会导致未定义的行为。

因此,可以得出结论:在C中,如果一个声明但未初始化的变量具有自动存储类别,其值是不确定的;如果具有静态存储类别,其值将根据其类型进行初始化。

0
0 Comments

在C语言中,声明但未初始化的变量会发生什么?它有一个值吗?

在C语言中,静态变量(文件作用域和函数静态)会被初始化为零。而非静态变量(局部变量)是不确定的。在给它们赋值之前读取它们会导致未定义行为。实际上,它们通常会在初始状态下具有一些荒谬的值,一些编译器甚至可能放入特定的固定值,以便在调试器中查看时更加明显。但严格来说,编译器可以做任何事情,从崩溃到通过你的鼻腔召唤恶魔。

为什么它被定义为未定义行为而不仅仅是“未定义/任意值”呢?这是因为一些CPU架构在其表示中有额外的标志位。一个现代的例子是Itanium处理器,它在其寄存器中有一个“Not a Thing”位。当然,C标准起草者考虑了一些较旧的体系结构。

尝试使用这些标志位设置的值可能会导致CPU异常,而这个操作实际上不应该失败(例如,整数加法或赋值给另一个变量)。如果你离开一个变量未初始化,编译器可能会选择一些随机的垃圾值,并且这些标志位被设置-这意味着触碰那个未初始化的变量可能是致命的。

为了解决这个问题,可以通过对变量进行初始化来避免未定义行为。例如:

int x = 0;

。这将确保变量具有一个确定的值,而不是一个不确定的值。

总之,声明但未初始化的变量在C语言中是不确定的,并且读取它们可能导致未定义行为。为了避免这种情况,应该始终初始化变量。

0