为何C语言函数f()二次及三次调用时未初始化i值可预测?
未初始化局部变量为何保留之前函数调用的数值?
问题描述
无法理解为何函数f()第二次调用时,未初始化的变量i的值为1234?原以为第一次f()执行完毕后,其栈帧会被弹出,此时i应是不可预测的值。同样,在调用g(5432)后第三次调用f()时,i的值突然变为5432,这是为什么?
代码示例
void f(); void g(int); void main() { f(); f(); g(5432); f(); } void f() { int i; printf("%d\n", i); i = 1234; } void g(int val) { printf("%d\n", val); }
运行输出
0 1234 5432 5432
原因解释
- 局部变量的存储特性:C语言中未初始化的局部变量属于自动存储类别,默认存在栈内存里。函数调用时会为局部变量分配栈帧,函数返回后,栈指针只是向上移动标记栈帧可复用,不会主动清空栈内的数据——之前存储的值会保留到被新数据覆盖为止。
- 第一次调用
f():此时i所在的栈内存是未初始化的随机值(本次输出0是环境栈初始化为0的结果,换个环境可能是其他数值),随后i被赋值为1234。函数返回后,栈里的1234并没有被清除。 - 第二次调用
f():函数再次分配栈帧时,刚好复用了第一次f()用的栈空间,i所在的内存位置还留着之前的1234,所以输出这个值。 - 调用
g(5432):函数g的参数val会存在栈内存中,输出后函数返回,栈里对应位置保留着5432。 - 第三次调用
f():再次复用栈空间时,i的位置刚好对应之前g参数val的存储位置,所以输出5432。
要特别注意:这种行为属于C标准定义的未定义行为,换个编译器、优化等级或者操作系统,运行结果可能完全不同,绝对不能在实际代码里依赖这种特性。
内容的提问来源于stack exchange,提问作者Disdainty
相关产品推荐
相关产品推荐

