C 如果未初始化,自动变量是否具有静态寿命?
我很好地理解了静态局部变量的概念:全局寿命,局部范围。类似地,我理解当程序流进入和离开变量的上下文时,自动变量会自动分配/释放C 如果未初始化,自动变量是否具有静态寿命?,c,static,scope,initialization,c99,C,Static,Scope,Initialization,C99,我很好地理解了静态局部变量的概念:全局寿命,局部范围。类似地,我理解当程序流进入和离开变量的上下文时,自动变量会自动分配/释放 #include <stdio.h> void test_var(void){ static unsigned foo = 0; unsigned bar = 0; printf(" %u %u\n", foo++, bar++); } int main(void){ printf("Foo Bar\n");
#include <stdio.h>
void test_var(void){
static unsigned foo = 0;
unsigned bar = 0;
printf(" %u %u\n", foo++, bar++);
}
int main(void){
printf("Foo Bar\n");
printf("--- ---\n");
for(unsigned x = 0; x < 10; x++){
test_var();
}
return 0;
}
让我困惑的是变量在未初始化时的行为:
#include <stdio.h>
void test_var(void){
static unsigned foo; /* not initialized */
unsigned bar; /* not initialized */
printf(" %u %u\n", foo++, bar++);
}
int main(void){
printf("Foo Bar\n");
printf("--- ---\n");
for(unsigned x = 0; x < 3; x++){
test_var();
}
return 0;
}
因此,静态变量的行为与预期一致——获得默认值0
,并在函数调用中保持不变;但是自动变量似乎也会持续存在——尽管它持有一个垃圾值,但它在每次调用中都会递增
发生这种情况是因为C标准中未定义行为,还是标准中有一套规则解释了这一点?C标准说,对象的寿命是保证其存储的时间(参见ISO/IEC 9899:TC3的6.2.4)。静态变量和全局变量的生命周期贯穿于整个程序,因此标准保证了上述行为。这些值在程序启动前初始化。对于automatic,对象的地址是恒定的,但只有在其生命周期内才能得到保证。所以,尽管bar在多次函数调用中似乎保持活动状态,但您不能保证它。 这也是为什么你应该总是初始化你的变量,在你使用它之前你永远不可能知道哪个变量在同一个地方 我稍微调整了程序,以同时打印静态变量和局部变量的地址:
#include <stdio.h>
void test_var(void){
static unsigned foo; /* not initialized */
unsigned bar; /* not initialized */
printf(" %u %u\t%p\t %p\n", foo++, bar++, &foo, &bar);
}
int main() {
printf("Foo Bar\n");
printf("--- ---\n");
for(unsigned x = 0; x < 3; x++){
test_var();
}
return 0;
}
这表明在我的机器上,每次调用时,静态
foo
和自动bar
都位于相同的地址,但这是巧合,C标准不能保证bar
始终位于相同的地址。在我看来很像未定义的行为。在test_var函数周围再添加一些变量和函数调用,“fun”可能会随之而来。这是未定义的行为。这可能是因为变量bar
总是放在同一个位置,并且在调用之间不会被覆盖。我几乎100%肯定这是一个重复的问题。因此,它似乎持续存在的原因可能是因为我的代码太过简单,以至于内存永远不会被覆盖?@VilhelmGray非常可能。如果你在循环体中调用另一个函数,并且在循环体中有两个参数,那么它就有可能重写“C++ >代码>代码的位置。静态变量的值,但在首次使用之前。@ C++的问题VILHELM Gray,C++中的OOP可能有所不同。我说得太快,忽略了语言。
Foo Bar
--- ---
0 2
1 3
2 4
3 5
4 6
5 7
6 8
7 9
8 10
9 11
#include <stdio.h>
void test_var(void){
static unsigned foo; /* not initialized */
unsigned bar; /* not initialized */
printf(" %u %u\t%p\t %p\n", foo++, bar++, &foo, &bar);
}
int main() {
printf("Foo Bar\n");
printf("--- ---\n");
for(unsigned x = 0; x < 3; x++){
test_var();
}
return 0;
}
Foo Bar
--- ---
0 33616 0x1067c 0xbee894fc
1 33617 0x1067c 0xbee894fc
2 33618 0x1067c 0xbee894fc