非初始化变量的默认值

时间:2014-03-14 21:47:09

标签: c undefined-behavior

我正在阅读有关调试的this tutorial。我在我的.c档案中粘贴了因子代码:

#include <stdio.h>

int main()
{
    int i, num, j;
    printf ("Enter the number: ");
    scanf ("%d", &num );

    for (i=1; i<num; i++)
        j=j*i;    

    printf("The factorial of %d is %d\n",num,j);
}

当我运行可执行文件时,它总是打印0,但是,教程的作者说它返回数字垃圾值。我已经用Google搜索了这个,我已经读过这是正确的,除了静态变量。所以它应该返回一个垃圾数而不是0

我认为这可能是由于不同版本的C,但指南是从2010年开始的。

为什么我总是看到0而不是垃圾值?

4 个答案:

答案 0 :(得分:3)

C99 draft standardC11 draft standard都表示未初始化的自动变量的值是不确定的,来自草案c99标准部分6.2.4 对象的存储持续时间段落 5 表示(强调我的):

  

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

标准草案将不确定定义为:

  

未指定的值或陷阱表示

,未指定的值定义为:

  

本国际标准规定的相关类型的有效值   在任何情况下选择值的要求

所以价值可以是任何东西。它可能随编译器,优化设置而变化,甚至可能因运行而异,但不能依赖它,因此任何使用不确定值的程序都在调用undefined behavior

标准规定,6.5.2.5 复合文字 17 中的一个示例中未定义此内容,其中包含:

  

请注意,如果使用迭代语句而不是显式goto和带标签的语句,则未命名对象的生命周期将仅为循环体,并且在下次输入p时将具有不确定的值,< strong>会导致未定义的行为。

Annex J.2 未定义的行为

中也包含了这一点
  

使用具有自动存储持续时间的对象的值   不确定(6.2.4,6.7.8,6.8)。

在某些非常具体的情况下,您可以对此类行为做出一些预测,演示文稿Deep C会进入其中。这些类型的检查应仅用作进一步了解系统如何工作的工具,甚至不应接近生产系统。

答案 1 :(得分:0)

您需要将j初始化为1.如果j恰好为零,则答案将始终为零(一种类型的垃圾)。如果j碰巧非零,那么你会得到不同的垃圾。使用未初始化的变量是未定义的行为; “undefined”并不排除在目前为止所做的测试中始终为零。

答案 2 :(得分:0)

某些系统的内存设置为0(例如Mac OS),因此当您初始化它时,您的变量通常会包含0,但这样做会导致不稳定的结果。

答案 3 :(得分:0)

你无法说出在这种情况下会发生什么,因为语言规范并没有说明会发生什么。事实上,它表示未初始化的非静态变量的值是不确定的。

这意味着它们可以是任何价值。它们可以在程序的不同运行中使用不同的值,或者在不同的编译器上编译代码时,或者在使用不同优化设置的同一编译器上编译时。或者在一周中的不同日期,国家法定假日或下午6点之后。

未初始化的变量甚至可以保存所谓的陷阱表示,这是一个对该类型无效的值。如果您访问这样的值,那么您就会陷入未定义行为的可怕世界,其中任何事情都可能发生。