为什么全局变量总是初始化为'0',但局部变量不是?

60

1
关闭,但最明显的原因没有提到:局部变量只是指向堆栈的指针,而堆栈随时都在变化。 - dagelf
4个回答

130

这是由于根据C标准规定的。原因在于效率:

  • 静态变量在编译时初始化,因为它们的地址是已知且固定的。将其初始化为0不会产生运行时成本。

  • 自动变量在不同调用中具有不同的地址,并且每次需要在运行时进行初始化,会产生运行时成本,但这可能是不必要的。如果需要初始化,则请进行请求。


1
好的回答 +1,全局变量是在编译时赋值为0对吧? - Grijesh Chauhan
7
如果全局变量没有被初始化为非零值,它们将在载入进程镜像并在main程序启动之前被设置为零。这是一次性的操作,与针对本地变量的“每次调用函数”操作相比。 - Jonathan Leffler
20
实际上,静态变量也会在运行时初始化。C运行时库(crt)将在调用main函数之前对它们进行初始化。当然,这只会发生一次,但仍然在运行时进行。 - Sil
13
同时,你不能在编译时初始化任何内容。程序需要启动并加载到内存中,以便你可以将内容清零(在这种情况下是bss节)。这是无法在编译时完成的,只能在运行时进行。谢谢。 - Sil
断言将运行时对象初始化为零没有成本并不完全正确。在通用多用户操作系统中,系统必须在将内存重新分配给另一个进程之前隐藏其他进程的数据,并且将新内存设置为零而不是其他值的边际成本为零。然而:(a)这仍然需要时间,并且它并不总是发生在进程启动期间;它可能会在执行过程中稍后第一次使用页面时进行按需处理... - Eric Postpischil
显示剩余5条评论

44

globalstatic变量在初始化时被存储在数据段 (DS) 中,在未初始化的情况下由符号 (BSS) 块开头存储。

这些变量具有固定的内存位置,并且内存是在编译时分配的。

因此,globalstatic 变量的默认值为 '0'

auto 变量存储在堆栈上,它们没有固定的内存位置。

内存是在运行时分配给 auto 变量,而不是在编译时分配。因此,auto 变量的默认值为垃圾值。


6
这并不完全正确。.bss在编译时未分配,实际上这就是引入.bss作为未初始化/零静态/全局变量的特殊部分的原因。只需存储大小信息,因此二进制文件不会被无用的数据(即零)破坏。在运行时,.bss变量将被初始化为零(与.data部分中的变量不同,在其中实际的初始值必须存储在二进制文件中)。除此之外,我认为这是更好的答案,+1 :-) - andreee

17

你选择了简单的变量,但请考虑:

void matrix_manipulation(void)
{
    int matrix1[100][100];
    int matrix2[100][100];
    int matrix3[100][100];

    /* code to read values for matrix1 from a file */
    /* code to read values for matrix2 from a file */
    /* code to multiply matrix1 by matrix2 storing the result in matrix3 */
    /* code to use matrix3 somehow */
}

如果系统将数组初始化为0,那么这些努力将会白费;初始化会被函数的其余部分覆盖。C语言尽可能避免隐藏的成本。


1
如果它们只是简单的变量,那么这个努力将会白费... - K-ballo
2
@K-ballo:是的,你说得对 — 但是当变量是相当大的数组、结构体或结构体数组时,代价就更加明显。即使初始化几十个整数变量并不太明显,但是几千个整数值就会变得明显起来。 - Jonathan Leffler
1
即使一个整数在内部循环中,只使用4个指令执行的东西中,也是显著的(+1指令)。 - Erik Aronesty

6

全局变量是在 main 函数开始之前分配和初始化的,而局部变量则随着程序实例在堆栈上生成。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接