默认情况下,C 中未初始化的局部变量是静态的吗?
Are uninitialized local variables in C static by default?
我最近了解到静态变量,它们在各种函数调用之间保留它们的值。然后我写了一些代码来测试它,希望它能完美运行。但后来我不小心删除了局部变量声明开头的 static 关键字,真正的问题来了。
这两个程序的输出是相似的,除了在声明过程中没有使用 static 关键字。
代码没有任何静态声明:
#include <stdio.h>
void up();
int main(){
up(); //Output: 1
up(); //Output: 2
return 0;
}
void up(){
int stvar;
stvar++;
printf("%d\n", stvar);
}
代码和静态声明:
#include <stdio.h>
void up();
int main(){
up(); //Output: 1
up(); //Output: 2
return 0;
}
void up(){
static int stvar;
stvar++;
printf("%d\n", stvar);
}
最后我尝试了这个,只初始化局部变量:
#include <stdio.h>
void up();
int main(){
up(); //Output: 1
up(); //Output: 1
return 0;
}
void up(){
int stvar = 0;
stvar++;
printf("%d\n", stvar);
}
这一次局部变量显示了它的自然行为。
我只想知道未初始化的局部变量默认是静态的吗?
使用未初始化的自动变量是危险的。
如果没有地址被占用,它是未定义的行为。
否则,就像您的情况一样, stvar
的值将不确定。它的值可以是任意的,甚至可以在访问之间改变。
始终初始化局部变量。
请注意,如果未明确初始化,具有静态存储的变量(全局变量和 static
)是 零 初始化。
不,默认情况下它们不是 static
。原则上,初始值可以是任何值。 Using the value could even be undefined behaviour。实际上,编译器会在堆栈上为变量选择一个内存位置,而变量的初始值是该内存位置中已经存在的任何值。
由于您没有 运行 第一个 up()
和第二个 up()
之间的任何其他代码,实际上您的程序可能会两次选择相同的位置,因此它仍然有以前的价值。如果您在两者之间调用另一个函数,该函数的局部变量将与 up()
的局部变量先前使用的 space 相同,这将覆盖第一个 up()
的值。
你当然不能依赖它。即使您不在中间调用任何其他函数,编译器也可能会“秘密地”添加一个(出于各种原因)。或者编译器可能决定将两次调用之间的堆栈调整为 up
,因此每次调用都可能为其局部变量获得不同的堆栈位置。
您也不能保证第一个值是 0。因为它恰好已经在该内存位置,所以它可能是前一个函数遗留下来的东西。 main
不是第一个被调用的函数;标准库中有一些函数在调用 main
.
之前进行设置工作
我最近了解到静态变量,它们在各种函数调用之间保留它们的值。然后我写了一些代码来测试它,希望它能完美运行。但后来我不小心删除了局部变量声明开头的 static 关键字,真正的问题来了。 这两个程序的输出是相似的,除了在声明过程中没有使用 static 关键字。
代码没有任何静态声明:
#include <stdio.h>
void up();
int main(){
up(); //Output: 1
up(); //Output: 2
return 0;
}
void up(){
int stvar;
stvar++;
printf("%d\n", stvar);
}
代码和静态声明:
#include <stdio.h>
void up();
int main(){
up(); //Output: 1
up(); //Output: 2
return 0;
}
void up(){
static int stvar;
stvar++;
printf("%d\n", stvar);
}
最后我尝试了这个,只初始化局部变量:
#include <stdio.h>
void up();
int main(){
up(); //Output: 1
up(); //Output: 1
return 0;
}
void up(){
int stvar = 0;
stvar++;
printf("%d\n", stvar);
}
这一次局部变量显示了它的自然行为。 我只想知道未初始化的局部变量默认是静态的吗?
使用未初始化的自动变量是危险的。
如果没有地址被占用,它是未定义的行为。
否则,就像您的情况一样, stvar
的值将不确定。它的值可以是任意的,甚至可以在访问之间改变。
始终初始化局部变量。
请注意,如果未明确初始化,具有静态存储的变量(全局变量和 static
)是 零 初始化。
不,默认情况下它们不是 static
。原则上,初始值可以是任何值。 Using the value could even be undefined behaviour。实际上,编译器会在堆栈上为变量选择一个内存位置,而变量的初始值是该内存位置中已经存在的任何值。
由于您没有 运行 第一个 up()
和第二个 up()
之间的任何其他代码,实际上您的程序可能会两次选择相同的位置,因此它仍然有以前的价值。如果您在两者之间调用另一个函数,该函数的局部变量将与 up()
的局部变量先前使用的 space 相同,这将覆盖第一个 up()
的值。
你当然不能依赖它。即使您不在中间调用任何其他函数,编译器也可能会“秘密地”添加一个(出于各种原因)。或者编译器可能决定将两次调用之间的堆栈调整为 up
,因此每次调用都可能为其局部变量获得不同的堆栈位置。
您也不能保证第一个值是 0。因为它恰好已经在该内存位置,所以它可能是前一个函数遗留下来的东西。 main
不是第一个被调用的函数;标准库中有一些函数在调用 main
.