最好将全局/静态变量初始化为零或保持未初始化

时间:2015-01-11 17:05:27

标签: c

1)宣布全球&静态变量,我们应该将它们初始化为0吗?虽然默认情况下它们会被初始化为0,是否有任何推荐的方法?

2)我们应该保持它们未初始化(它们转到BSS部分)还是将它们初始化为0(它们转到内存的数据部分)?那个(他们去哪个记忆区域)会有什么影响吗?将它们保持为未初始化会导致程序的二进制图像的小尺寸(如果是,请让我知道它将如何导致小尺寸&这是否是保持它们未初始化的原因)?

3)C编码标准是否对此有所说明,或者有任何专业人士和是否更喜欢一种方法而不是另一种?

5 个答案:

答案 0 :(得分:3)

您似乎在问:"是否建议将静态存储持续时间的对象显式初始化为零,即使它们无论如何都是零初始化?"

如果我的解释是正确的,答案是坚定的

某些公司可能会推荐一些编码标准,但这是一个愚蠢的建议。

至于他们最终的内存区域,无论你手动初始化它们都绝对没有任何关系。

答案 1 :(得分:3)

一个不错的编译器应该完全相同地处理这两个全局变量:

int x;
int y = 0;

它也应该同样对待这两个静态变量:

int f() {
    static int x;
    static int y = 0;
}

同样地,我的意思是它们具有相同的值并存储在同一程序段中。您应该使用您认为最易读的那个。

至于这是否占用了可执行文件中较少的空间,这取决于您的可执行格式。对于elf,这在linux和其他unix上很常见,答案是零初始化变量会占用更少的空间。这意味着:

static int x;     // no space.
static int y = 0; // no space.
static int z = 1; // takes space.

答案 2 :(得分:3)

不明确地初始化它们很常见。也许有编码风格指南建议显式初始化。

C标准规定了一个技术差异:如果隐式初始化变量("暂定定义"),可以稍后明确初始化:

int foo;
int foo = 1; // valid

int bar = 0;
int bar = 0; // invalid, even though initialized to the same value

这也适用于数组大小(它们默认为一个元素),我认为这是一个错误,并建议明确给出大小。但这基本上是一种品味问题。

C标准对内存部分一无所知;默认初始化和显式初始化的变量不会对严格符合代码产生影响。对于GCC,似乎存在一些差异(对于非可移植代码)。 C标准未定义以下内容,但GCC(在Linux上使用GNU ld进行测试,x86 32位,ELF)接受它:

<强> foo.c的

int foo = 42;

<强>的main.c

#include <stdio.h>

int foo;

int main(void) { printf("%d\n", foo); }

运行时编译并链接gcc -std=c99 -pedantic并输出42。在 main.c 中显式初始化foo时,链接器会失败,抱怨foo的多个定义。我在GCC文档中找不到相关内容,但C标准(C11,n1570草案)列在&#34;共同扩展&#34; (J.5.11 p1):

  

对象的标识符可能有多个外部定义,无论是否明确使用关键字extern;如果定义不同意或不同   一个被初始化,行为未定义(6.9.2)。

对于生成的ELF,我在我的平台上找不到任何差异(虽然我刚刚进行了实验,如上所述,我无法找到记录此行为的位置),因此差异似乎只是在语义上(仅适用于非便携式代码),效率没有差异。

答案 3 :(得分:2)

1.作为风格和实践的问题,最好将它们初始化为0.

2.未初始化的数据不占用可执行格式的任何空间,因此零初始化数据(因为OS加载器有责任为该区域分配零初始化内存)。 elf标头仅保存未初始化区域所需的总空间。

3.C标准要求将全局/静态变量初始化为零。

请注意,在没有动态创建进程/线程机制的嵌入式系统中,启动代码负责将全局/静态初始化为零,出于性能考虑,可以初始化区域按要求。请注意,这种实现形式不符合C标准,可能有助于改善启动时间。

答案 4 :(得分:2)

初始化您在程序中使用的变量将会很好。如果你没有初始化它们,那么就有可能最终采取垃圾价值&#34;来自你的变量。

但是,在全局变量的情况下,由于它们被自动初始化为零,因此无需自己将它们初始化为零。

根据我迄今为止从计算机编程讲座中学到的知识,使用全局变量并不是一种好的编程方式,因为变量应始终具有最小的范围。这背后的论点是,每次增加范围时,您都会有更多可能修改变量的代码,从而在解决方案中引入更多复杂性。在局部变量的情况下,它们的范围是有限的,并且必须初始化它们,否则存在使用&#34;垃圾值的危险&#34;。