写点什么

一道 2016 年 nice 的笔试题引发的思考

作者:芒果酱
  • 2022 年 7 月 13 日
  • 本文字数:923 字

    阅读完需:约 3 分钟



上一篇文章的问题代码,我认为有必要单独拿出来讲讲!

一个有问题的代码

int main(){  int i = 0;  int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };  for (i = 0; i <=12; i++)  {    arr[i] = 0;    printf("hehe\n");  }  return 0;}
复制代码


执行结果:死循环打印 hehe




为了发现问题:打印第几次打印


int main(){  int i = 0;  int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };  for (i = 0; i <=12; i++)  {    arr[i] = 0;    printf("hehe\n");    printf("第%d次打印\n",i);  }  return 0;}
复制代码



i 不能变为 12




调试结果:



将第数组元素下标为 12 的值也改成 0 时,i 也恢复为 0,所以造成了死循环


**为什么呢?

猜想两个占用同一块空间

->验证






深入理解上述程序 err 原因

栈区先使用高地址,再使用低地址. 先定义变量 i,所以 i 在高地址位置,然后再定义数组,二者相隔几个地址未知


arr 和 i 中隔了几个元素是未知的,取决于编译器




变量和数组相隔距离

VC6.0中: arr和i是紧挨着的VS2013-VS2019 arr和i中间有两个元素gcc: arr和i之间放一个元素
复制代码




所以在 VC6.0 条件下,arr[10],写成 i <= 10 时就死循环了

如何解释:

i和arr是局部变量,放在栈区,栈区的使用习惯是先使用高地址,再使用低地址画出栈区内存,上面低地址,下面高地址,先把高地址的空间使用了i在下面创建,arr在上面创建,
又因为随着数组下标的增长,元素的地址又低到高变化随着数组下标的越界访问,就可能覆盖循环变量i(二者占用同一块空间)
复制代码




问:当 i 和 arr 的创建反过来时:直接报错,不会死循环


因为内存布局发生变化


int main(){  int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };  int i = 0;  for (i = 0; i <=12; i++)  {    arr[i] = 0;    printf("hehe\n");    printf("第%d次打印\n",i);  }  return 0;}
复制代码


执行结果:报错


注意


程序越界有一个报错的时间点,程序停下来时才报错,死循环了没时间报错





若改成 release 版本:



执行结果:打印 13 个 hehe




在 Debug 情况下: i 确实在数组后面存放, i 的地址比数组地址大





而在 Release 版本:数组的地址更大 编译器进行了优化了,因为考虑到放后面可能出错





这也证明了 Release 版本确实可以优化




今天就先到这吧~感谢你能看到这里!希望对你有所帮助!欢迎老铁们点个关注订阅这个专题! 同时欢迎大佬们批评指正!

发布于: 刚刚阅读数: 3
用户头像

芒果酱

关注

我们都在努力奔跑,我们都是追梦人! 2022.02.14 加入

个人宣言:功崇惟志,业广惟勤 个人简介: 0.在校大学生 1.CSDN:C/C++领域新星创作者 2.掘金LV3创作者 3.华为云开发者社区云享专家 4.阿里云开发者社区专家博主 5.InfoQ创作者

评论

发布
暂无评论
一道2016年nice的笔试题引发的思考_7 月月更_芒果酱_InfoQ写作社区