【问题标题】:initial value of int array in CC中int数组的初始值
【发布时间】:2010-11-27 16:55:04
【问题描述】:

当像这样在 C 中声明一个数组时:

int array[10];

整数的初始值是多少?我使用不同的编译器得到不同的结果,我想知道它是否与编译器或操作系统有关。

【问题讨论】:

    标签: c arrays compiler-construction


    【解决方案1】:

    如果数组在函数中声明,则值未定义。函数中的int x[10]; 表示:在不进行任何初始化的情况下获得10-int-size 内存区域的所有权。如果数组被声明为全局数组或函数中的static,则如果所有元素尚未初始化,则将其初始化为零。

    【讨论】:

    • 正确。除非它是全局的,否则它将包含之前那段内存中的任何随机垃圾。与编译器无关。如果你特别想要里面的东西,就把它放在那里。
    • @buzali 一些编译器/工具链将始终将变量和分配的内存归零,最常见的是当您在“调试”模式下构建时(未启用优化)。这通常是为了创建一个确定性的调试环境,以便在您对代码进行原型设计时忘记初始化变量。另一种可能性是数组使用的内存恰好包含零。
    • 不正确。变量范围无关紧要 - 存储类。
    • @buzali:不,这不是你想要的。如果要将数组初始化为零,请编写int array[10] = {0};。让编译器自动执行它只是意味着您正在编写仅在调试模式下工作的代码,并且在您发布它时会中断,或者其他人使用不同的选项编译它。
    • @AraK:在你的答案中添加一个static 函数内定义的变量也将被初始化为零可能也是值得的。
    【解决方案2】:

    按照标准的规定,所有全局和函数静态变量都会自动初始化为 0。自动变量不会被初始化。

    int a[10];  // global - all elements are initialised to 0
    
    void foo(void) {
        int b[10];    // automatic storage - contain junk
        static int c[10]; // static - initialised to 0
    }
    

    但是,无论其存储类如何,始终手动初始化函数变量是一个好习惯。要将所有数组元素设置为 0,您只需将第一个数组项分配为 0 - 省略的元素将自动设置为 0:

    int b[10] = {0};
    

    【讨论】:

    • 为了迂腐,文件范围变量(全局变量)具有存储类静态,这就是它们被初始化为 0 的原因。
    • @John 是的,但是因为文件级别的静态具有不同的含义,所以我只是将其称为“全局”,无论是文件全局还是程序全局
    • 我不明白为什么浪费周期来初始化一个大缓冲区是个好习惯,在下一行中,您将加载来自文件/网络的数据。
    【解决方案3】:

    为什么函数局部变量(auto 存储类)没有初始化而其他一切都初始化了?

    C 接近硬件;这是它最大的力量,也是它最大的危险。 auto 存储类对象具有随机初始值的原因是因为它们是在堆栈上分配的,并且设计决定不自动清除这些(部分是因为它们需要在每次函数调用时清除)。

    另一方面,非auto 对象只需清除一次。另外,出于安全原因,操作系统必须清除分配的页面。所以这里的设计决定是指定零初始化。为什么堆栈的安全性也不是问题?实际上,一开始它是清除的。您看到的垃圾来自您自己的程序调用帧的早期实例以及它们调用的库代码。

    最终结果是快速、节省内存的代码。组装的所有优点,没有任何痛苦。在 dmr 发明 C 之前,像 Basic 和整个 OS 内核这样的“HLL”实际上是作为巨大的汇编程序实现的。 (在像 IBM 这样的地方有一些例外。)

    【讨论】:

      【解决方案4】:

      根据 C 标准,6.7.8(注 10):

      如果一个对象具有自动 存储持续时间未初始化 明确地,它的值是 不确定。

      所以这取决于编译器。使用 MSVC,调试版本将使用 0xcc 初始化自动变量,而非调试版本根本不会初始化这些变量。

      【讨论】:

        【解决方案5】:

        C 变量声明只是告诉编译器留出并为您命名一个内存区域。对于自动变量,也称为堆栈变量,该内存中的值与之前的值没有变化。程序启动时将全局变量和静态变量设置为零。

        未优化调试模式下的某些编译器将自动变量设置为零。但是,在较新的编译器中,将值设置为已知的错误值已变得很常见,这样程序员就不会在不知不觉中编写依赖于设置零的代码。

        为了让编译器为你设置一个数组为零,你可以这样写:

        int array[10] = {0};
        

        更好的是用它应该有的值来设置数组。这样效率更高,并且避免了两次写入数组。

        【讨论】:

        • 你知道如何告诉编译器将值设置为零吗?我正在使用 GCC... 是否有任何调试参数可以做到这一点?
        • 不要依赖编译器来初始化数组,使用像 Zan 建议的显式初始化器。即使当前的 gcc 在某些调试模式下将数组归零,下一个可能会决定用完全不同的值填充它们,让您在 5 年后很难找到错误。只需输入额外的 5 个字符并使用 int array[10] = {0};
        • 显然不正确。数据段中的变量始终为零。
        • 远不总是归零
        【解决方案6】:

        在大多数最新的编译器(例如 gcc/vc++)中,部分初始化的本地数组/结构成员默认初始化为零(int)、NULL(char/char string)、0.000000(float/double)。

        除了上面的局部数组/结构数据外,静态(全局/局部)和全局空间成员也保持相同的属性。

        int a[5] = {0,1,2};
        printf("%d %d %d\n",*a, *(a+2), *(a+4));
        
        struct s1
        {
        int i1;
        int i2;
        int i3;
        char c;
        char str[5];
        };
        
        struct s1 s11 = {1};
            printf("%d %d %d %c %s\n",s11.i1,s11.i2, s11.i3, s11.c, s11.str);
            if(!s11.c)
                printf("s11.c is null\n");
            if(!*(s11.str))
                printf("s11.str is null\n");
        

        在 gcc/vc++ 中,输出应该是:

        0 2 0 1 0 0 0.000000 s11.c 为空 s11.str 为空

        【讨论】:

          【解决方案7】:

          来自http://www.cplusplus.com/doc/tutorial/arrays/的短信

          总结:

          初始化数组。当声明一个 本地范围的常规数组(在 函数,例如),如果我们不 否则,其元素将 不被初始化为任何值 默认,所以他们的内容将是 在我们存储一些值之前不确定 在他们之中。全局元素和 另一方面,静态数组是 用他们的自动初始化 默认值,这对于所有 基本类型,这意味着它们是 用零填充。

          在本地和全局这两种情况下,当 我们声明一个数组,我们有 分配初始值的可能性 通过 将值括在大括号 {} 中。 例如:

          int billy [5] = { 16, 2, 77, 40, 12071 };
          

          【讨论】:

            【解决方案8】:

            来自 C 标准的相关部分(重点是我的):

            5.1.2 执行环境

            所有具有静态存储持续时间的对象应在程序启动前初始化(设置为其初始值)。

            6.2.4 对象的存储时长

            使用外部或内部链接或存储类说明符 static 声明其标识符的对象具有静态存储持续时间。

            6.2.5 类型

            数组和结构类型统称为聚合类型。

            6.7.8 初始化

            如果具有自动存储持续时间的对象未显式初始化,则其值不确定。如果具有静态存储持续时间的对象未显式初始化

            • 如果有指针类型,则初始化为空指针
            • 如果是算术类型,则初始化为(正或无符号)
            • 如果是聚合,则每个成员都根据这些规则进行初始化(递归);
            • 如果是联合,则根据这些规则(递归)初始化第一个命名成员。

            【讨论】:

              【解决方案9】:

              这取决于您的阵列的位置。 如果它是全局/静态数组,它将成为bss 部分的一部分,这意味着它将在运行时由 C 复制例程初始化为零。 如果是函数内的局部数组,则位于stack内,初始值未知。

              【讨论】:

                【解决方案10】:

                如果数组是在函数内部声明的,那么它的值是未定义的,但是如果数组声明为全局数组或者它在函数内部是静态的,那么数组的默认值为 0。

                【讨论】:

                • 这正是所选答案所说的。请在将来查看其他答案,特别是如果问题已经得到解答。
                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2015-09-05
                • 2012-11-10
                • 1970-01-01
                • 1970-01-01
                • 2011-07-10
                • 2021-04-08
                相关资源
                最近更新 更多