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

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

回顾上文:


一个有问题的代码

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;
}
复制代码

image.pngi不能变为12


调试结果:

image.png

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

**为什么呢?


猜想两个占用同一块空间

->验证

image.png




深入理解上述程序err原因


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

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

image.png



变量和数组相隔距离


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;
}
复制代码


执行结果:报错

注意

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

image.png


若改成release版本:

image.png

执行结果:打印13个hehe


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

image.png


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

image.png


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

相关文章
|
10月前
|
C语言
C语言--每日五道选择题--Day10
C语言--每日五道选择题--Day10
|
10月前
|
C语言
C语言--每日五道选择题--Day9
C语言--每日五道选择题--Day9
C语言--每日五道选择题--Day9
|
10月前
|
编译器 C语言
C语言--每日五道选择题--Day14
C语言--每日五道选择题--Day14
|
2月前
|
存储 C语言 C++
PTA—C语言期末复习(选择题)
PTA—C语言期末复习(选择题)
|
3月前
|
存储 C语言 C++
【C语言刷题系列】水仙花数的打印及进阶
【C语言刷题系列】水仙花数的打印及进阶
|
4月前
|
C语言
C语言部分期末答案(来自PTA)
C语言部分期末答案(来自PTA)
|
4月前
|
C语言
C语言--每日五道选择题--Day19
C语言--每日五道选择题--Day19
C语言--每日五道选择题--Day19
|
4月前
|
C语言 C++
C语言--每日五道选择题--Day23
C语言--每日五道选择题--Day23
|
4月前
|
小程序 C语言 C++
C语言--每日五道选择题--Day21
C语言--每日五道选择题--Day21
|
10月前
sizeof运算与strlen函数的面试笔试题(排版很舒服)
sizeof运算与strlen函数的面试笔试题(排版很舒服)