据我所知,每次调用函数后都会丢弃局部变量。但是当我执行这段代码时,变量保留了它们之前的值。这是什么行为?
编译器:gcc 4.8.4
#include<stdio.h>
void t();
int main(void){
t();
t();
t();
return 0;
}
void t(){
int i;
i++;
printf("%d\n",i);
}
输出:
4bh1@mybox:~/C-fi$ ./test
1
2
3
答案 0 :(得分:15)
程序的行为未定义。 i
未初始化,因此除了设置其值之外,i
的任何使用都是未定义的行为。
您看到的最有可能是i
获得相同的#34;堆叠空间&#34;每次分配给它,所以你只是重复使用以前的值。
请注意,当int
(或任何类型)超出范围时,编译器不会将其值重置为可能会浪费cpu周期的值。这就是为什么你可以看到值增加,因为它只是重用内存空间中的内容。
答案 1 :(得分:3)
这是堆叠人
在这种特殊情况下,它可能与函数中变量的内存分配方式有关。
为称为堆栈的函数变量保留了一个连续的内存块。
当你调用一个函数时,堆栈的一部分是为该函数保留的,并且存储了该函数中变量的值。
退出函数时,堆中的部分不再被保留,并将被下一个被调用的函数使用。但是,它中的值不为零,值保持不变。
因此,在这种情况下,如果你没有初始化你的函数变量,那么它将包含堆栈中的任何内容。
在这种情况下,由于你一遍又一遍地调用同一个函数,所以剩下的东西将是可预测的。但在大多数情况下,你会遇到问题并且它不可预测。
例如,如果您在其间调用不同的函数。
在
之间调用其他函数时中断#include<stdio.h>
void t();
void otherFunction();
int main(void){
t();
otherFunction();
t();
t();
return 0;
}
void t(){
int i;
i++;
printf("%d\n",i);
}
void otherFunction(){
int x = 10;
}
输出:
1
11
12
如果在堆栈中更深入地调用x(),它也不会表现相同:
从堆栈中的不同深度调用时中断
#include<stdio.h>
void t();
void callT();
int main(void){
t();
callT();
t();
t();
return 0;
}
void t(){
int i;
i++;
printf("%d\n",i);
}
void callT(){
t();
}
输出:
1
1
1
2
谈论未定义的行为,我甚至无法解释。
在我们的示例中使用int
或在我们的函数中没有使用更糟糕。堆栈不知道堆栈中的数据类型只是一堆字节。因此,您最终可能会将数据错误地解释为另一种类型。
例如,其中一个函数使用float而不是int。
使用不同类型时中断
#include<stdio.h>
void t();
void assignFloat();
int main(void){
t();
assignFloat();
t();
t();
return 0;
}
void t(){
int i;
i++;
printf("%d\n",i);
}
void assignFloat(){
float x = 10;
}
输出:
1
1092616193
1092616194
这不是你总会得到的行为,行为是&#34;未定义&#34;这意味着您无法预测从编译器到编译器甚至从一个编译器配置到另一个编译器配置的行为。未定义意味着它不可靠,你不应该这样做。
本答案中的示例使用以下方法进行测试:
g ++(GCC)5.3.1 20151207(Red Hat 5.3.1-2)
使用在线工具:
答案 2 :(得分:0)
您应该初始化变量i
。您还可以使用void
作为t()
的签名。
这是一个更新版本(也可以%d
使用printf
自由使用):
#include<stdio.h>
void t(void);
int main(void){
t();
t();
t();
return 0;
}
void t(void){
int i = 0;
i++;
printf("%d \n",i);
}