您的位置:首页 > 编程语言 > C语言/C++

由c++循环中局部变量地址不变而引发的思考

2018-01-05 19:42 1751 查看
今天在用c++刷题的时候出现了一个bug,算法题所以免不了循环输入,而所有的代码自然也都嵌套在那个大循环中了。但是问题出现在:我在一个函数(不是main函数)的开头定义了一些局部变量(这个函数在程序中会被循环调用),但是既然是另外一个函数中定义的变量,我想着应该会在函数退出后自动释放了,那也就不需要每次循环都初始化一遍了。

然而事实上,如果不去给它初始化值的话,局部变量每次被声明后所在的地址是相同的,最可怕的是地址相同的话,里面的值就是上一次运行结束后的值。这也就意味着,c++在循环里面定义的变量的值在逻辑上是具有传递性的,当然可靠性不一定能保证。

下面直接放测试代码截图:

编译环境:codeblocks,语言:c++

第一张图:可以看出在
make
函数中,如果不初始化
i
i
的值就是一个乱七八糟的数,但是初始化一次之后,即便以后不再初始化了,值也保留了下来。这很容易让人联想到
i
的地址一直是不变的,所以下面就测试了一下地址。



第二张图:上面说到值可以“继承”下来,那么地址真的不变吗?从下图中看出,地址确实是不变的,每次调用该函数后产生的变量
i
的地址都相同。这就让人疑惑了,它是根据什么来分配地址的呢?是请求分配地址的时间吗?于是进行了第三个实验。



第三张图:这一次在
make
函数中分情况定义了两个不同名称的局部变量,如果传进来的参数t为偶数,就定义变量
i
,并输出
i
的地址,如果传进来的参数
t
为奇数,就定义变量
j
,然后输出它的地址。神奇的一幕发生了,
i
的地址全都是相同的,
j
的地址也都是相同的,但是
i
j
的地址是不同的。从第一次申请空间的时间来看,
j
i
之后,因此根据
c++
局部变量控件分配到栈里,是从大到小的顺序,
j
的地址比
i
小4是没错的。但是第一次循环中
i
的地址如果被释放,第二次进来申请
j
的地址应该和第一次
i
的地址是相同的,然而事实并没有。而编译器如果确实是按照顺序分配空间的话,第一次的i的空间有可能根本就没有被真正的释放,只是以某种外界不可访问的方式存在。



论坛里看到有人说
栈上的内存是顺序分配的, pop出来,再push进去。还是在原来的位置
,这种说法应该是错误的,不然图三中
j
的地址应该和
i
的地址相同。

但是具体的原因仍旧不得而知了,希望以后能搞清楚这个问题。但是在刷题中要注意的是,在循环中,即便局部变量的申明也必须初始化!!!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息