C局部变量重用

据我所知,每次调用函数后都会丢弃局部变量。 但是当我执行这段代码时,变量保留了它们之前的值。 这是什么行为?

编译器:gcc 4.8.4

#include 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 

程序的行为未定义。 i是未初始化的,所以除了设置其值之外ii任何使用都是未定义的行为。

你很可能看到的是i每次都获得相同的“堆栈空间”,所以你只是重复使用之前的值。

请注意,当int (或任何类型)超出范围时,编译器不会将其值重置为某些内容,因为这会浪费cpu周期。 这就是为什么你可以看到值增加,因为它只是重用内存空间中的内容。

这是堆叠的人

在这种特殊情况下,它可能与函数中变量的内存分配方式有关。

存在为称为堆栈的函数变量保留的连续内存块。

当您调用一个函数时,该函数的一部分是为该函数保留的,并且该函数的值存储在该函数中。

当您退出函数时,堆中的部分不再被保留,并将被下一个被调用的函数使用。 但是,它中的值不是零,值仍然存在。

所以在这种情况下,如果你没有初始化你的函数变量,它将包含堆栈中发生的任何事情。

在这种情况下,因为你一遍又一遍地调用同一个函数,所剩下的将是可预测的。 但在大多数情况下,你会遇到问题而且无法预测。

例如,如果您在其间调用不同的函数。

在两者之间调用不同的函数时中断

 #include 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 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 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 

这不是您总是会得到的行为,行为是“未定义的”,这意味着您无法预测从编译器到编译器甚至从一个编译器配置到另一个编译器配置的行为。 未定义意味着它不可靠,你不应该这样做。

本答案中的示例使用以下方法进行测试:

g ++(GCC)5.3.1 20151207(Red Hat 5.3.1-2)

使用在线工具:

http://www.tutorialspoint.com/compile_cpp_online.php

你应该初始化你的变量i 。 您还可以使用void作为t()的签名。

这是一个更新版本(也可以自由地使用%dprintf ):

 #include void t(void); int main(void){ t(); t(); t(); return 0; } void t(void){ int i = 0; i++; printf("%d \n",i); }