C中int数组的初始值-为什么?

时间:2019-07-03 13:58:53

标签: c arrays

为什么是

的值
int array[10];

在函数中声明时未定义,并且在声明为0时被static初始化吗?

我一直在阅读this question的答案,很明显

  

[函数中的表达式int array[10];]的意思是:无需进行任何初始化即可获取10 int大小的内存区域的所有权。如果将数组声明为全局1或函数中的静态,则所有尚未初始化的元素都将初始化为零。

问题:为什么这种行为?编译器程序员是否会决定(出于特定原因)?使用的特定编译器可以做些不同的事情吗?

为什么要问这个问题:之所以问这个问题,是因为我想使我的代码在体系结构/编译器之间可移植。为了确保它,我知道我总是可以初始化声明的数组。但是,这意味着我只会为此操作浪费宝贵的时间。那么,哪个是正确的决定?

4 个答案:

答案 0 :(得分:6)

自动int array[10];不会隐式归零,因为归零需要时间,您可能不需要将其归零。此外,您不仅要付出一次代价,而且每次控件超出初始化变量时都要付出代价。

静态/全局int array[10]; 隐式归零,因为静态/全局变量是在加载时分配的。内存将从OS刷新,并且如果OS完全具有安全意识,则内存将已经为零。否则,加载代码(操作系统或动态链接器)将必须将它们归零(因为C标准要求这样做),但是对于所有全局变量/静态变量,它应该能够在一次调用memset的情况下做到这一点。与一次将每个静态/全局变量清零相比,效率要高得多。

此初始化完成一次。即使函数内部的static仅被初始化一次,即使它们具有非零的初始值设定项(例如static int x = 42;。这也是为什么C要求static的初始值设定项为常量表达式的原因。)

由于所有全局变量/静态变量的加载时间清零是OS保证的或可以有效实施的,因此它也可能是标准保证的,从而使程序员的生活更轻松。

答案 1 :(得分:4)

这些值不是不确定的而是不确定的,并且它的行为是这样的,因为标准如此规定。

C standard的第6.7.9p10节关于初始化状态:

  

如果具有自动存储持续时间的对象不是   显式初始化,其值不确定。如果   具有静态或线程存储持续时间的对象不是   显式初始化,然后:

     
      
  • 如果具有指针类型,则将其初始化为空指针;
  •   
  • 如果具有算术类型,则将其初始化为(正数或无符号)零;
  •   
  • 如果是聚合,则根据这些规则(递归)初始化每个成员,并将任何填充初始化为零位;
  •   
  • 如果是联合,则根据这些规则初始化(递归)第一个命名成员,并初始化任何填充   到零位;
  •   

因此,对于在文件作用域或static定义的任何变量,您都可以放心地假定值是零初始化的。对于在函数或范围内声明的变量,您不能对未初始化的变量做任何假设。

为什么,全局/静态变量是在程序启动时甚至在编译时初始化的,而局部变量每次在进入作用域时都必须初始化,这会花费时间。

答案 2 :(得分:3)

未在堆栈分配/局部变量中定义变量初始值的原因是效率。 C标准要求您的程序分配您的数组,然后填充它:

int array[10];
for (i = 0; i < 10; ++i)
    array[i] = i * 42;

在这种情况下,任何初始化都是没有意义的,因此C标准希望避免这种情况。

如果您的程序需要将这些值初始化为零,则可以明确地做到这一点:

int array[10] = {0}; // initialize to zero so the accumulation below works
while (condition)
{
    ... // some code
    for (i = 0; i < 10; ++i)
        array[i] += other_array[i];
}

由您决定是否初始化,因为您应该知道程序的行为。对于不同的阵列,此决定将有所不同。

但是,此决定将不依赖于编译器-它们都符合标准。关于可移植性的一点细节-如果您不初始化数组,而在使用特定的编译器时仍看到其中的全零-请勿上当。值仍未定义;您不能依靠它们为0。

其他一些语言认为,零初始化即使是多余的也足够便宜,并且其优点(安全性)大于缺点(性能)。在C语言中,性能更为重要,因此另行决定。

答案 3 :(得分:1)

C的哲学是:a)始终信任程序员,并且b)在执行速度上优先于程序员便利。 C假定程序员处于最佳位置,以了解是否需要将数组(或任何其他auto变量) 初始化为特定值,如果是,则足够聪明来编写代码自行完成。否则,不会浪费CPU周期。

对于数组访问的边界检查,对NULL对指针解除引用的检查,等等。

这同时是C语言的最大优势(占地面积小的快速代码)和最大的弱点(使代码安全可靠的体力劳动)。