全局和静态对象使用其类型的默认值进行初始化(整数为 0,浮点数为 0.0,指针为 NULL 等)
不能依赖其他未初始化的值。
下面是一个简单的解释:大多数实现都将所有局部变量放在一个堆栈上。当您声明局部变量或调用函数时,此堆栈会增长,而当您执行相反的操作时会缩小 - 退出变量的范围或从函数返回。
现在让我们看一个程序:
void good()
{
int p = 2;
printf("%d", p);
}
void notgood()
{
int p;
printf("%d", p);
}
int main()
{
good();
notgood();
notgood();
}
这是程序开始时的堆栈(堆栈向下增长)。堆栈指针始终指向顶部元素(由箭头表示):
|---------------------|
|main's return address| <-- stack pointer
接下来是在good()被调用后立即:
|---------------------|
|main's return address|
|good's return address| <-- stack pointer
接下来我们声明 p 并用 2 初始化它:
|---------------------|
|main's return address|
|good's return address|
|value 2 (variable p) | <-- stack pointer
之后,我们调用 printf:
|---------------------|
|main's return address|
|good's return address|
|value 2 (variable p) |
|value 2 (parameter) |
|format string address|
|printf's return addr |
|#printf's frame# | <-- stack pointer
返回时printf,返回地址和参数从堆栈中弹出,但不会从内存中删除。那将是低效的。我们只是减少堆栈指针。
|---------------------|
|main's return address|
|good's return address|
|value 2 (variable p) | <-- stack pointer
|value 2 (parameter) |
|format string address|
|printf's return addr |
|#printf's frame# |
接下来,我们的good()函数返回到 main:
|---------------------|
|main's return address| <-- stack pointer
|good's return address|
|value 2 (variable p) |
|value 2 (parameter) |
|format string address|
|printf's return addr |
|#printf's frame# |
打电话notgood。堆栈上的任何垃圾都会被覆盖:
|---------------------|
|main's return address|
|notgood's return addr| <-- stack pointer
|value 2 (variable p) |
|value 2 (parameter) |
|format string address|
|printf's return addr |
|#printf's frame# |
声明变量(分配空间),但我们不初始化。因此,旧的垃圾值仍然存在:
|---------------------|
|main's return address|
|notgood's return addr|
|value 2 (variable p) | <-- stack pointer
|value 2 (parameter) |
|format string address|
|printf's return addr |
|#printf's frame# |
接下来,我们再次调用 printf。请注意,它的返回地址实际上发生了变化,因此旧垃圾在堆栈上被覆盖:
|---------------------|
|main's return address|
|notgood's return addr|
|value 2 (variable p) |
|value 2 (parameter) |
|format string address|
|printf's return addr |
|#printf's frame# | <-- stack pointer
因此,如您所见,如果您不初始化变量,它们将采用堆栈上的任何值。
请注意,该程序可能无法运行,因为编译器可能会优化某些函数调用。