每天学一点系列~诡异的死循环

Posted 白龙码~

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了每天学一点系列~诡异的死循环相关的知识,希望对你有一定的参考价值。


在这里插入图片描述

Part I、题目分享

《C陷阱与缺陷》中有这样一个例题:

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

请问:这个程序的输出是什么?
10个hello world?
13个hello world?
还是由于越界访问而报错?
都不是!
我们放到VS2019下运行发现——
在这里插入图片描述
他死循环了!?什么情况?让我们深度剖析一下这道题吧!

Part II、题目剖析

1、计算机的内存分配原则

计算机有这样的变量内存分配原则:

对于先申请内存的变量,将高地址的内存分配给它

什么意思呢?
在这道题中我们看到:我们首先创建了变量i,然后创建了数组arr,因此在程序编译运行时,计算机会将高地址的内存优先分配给i,然后再分配给数组arr
也就是:
在这里插入图片描述

2、数组的内存分配原则

在数组中,内存的分配原则如下:

数组元素从低地址开始,往高地址分布,且下标为0的地址最低

即:
在这里插入图片描述

3、调试程序

由于数组有10个元素,因此下标0~9时为正常的数组元素访问,该程序将数组内容全部改为0;

i运行到10时将arr[10]改为0
在这里插入图片描述
此时屏幕打印11个hello world
在这里插入图片描述

i运行到11时将arr[11]改为0
在这里插入图片描述
此时屏幕打印12个hello world
在这里插入图片描述
然而i等于12时,arr[12]被改为0,i也很诡异地变成了0
在这里插入图片描述

到这里我们就不难理解为什么这个程序会死循环了;
可这是为什么呢?
i和arr[12]都在一瞬间变成了0,是否意味着:它们两个的地址是相同的?
我们在调试中取得i和arr[12]的地址:
在这里插入图片描述
比较发现:二者相同
这是巧合吗?还是故意的?

根据上面我们了解到的计算机内存分配以及数组内存分配原理,我们可以由此推测i和arr的内存布局为:
在这里插入图片描述
结合这幅图,那么一切就都说得通了:当arr[12]改为0时,由于i和arr[12]地址相同,所以i也被改为12,因此该程序死循环!

Part III、今日小结

从这道题中我们应当意识到:随着学习的深入,从代码的表象会越来越难地看出问题的本质,想要更优质的学习,必须从根源理解代码的原理与机制!

Part IV、系列文章索引

【每天学一点系列~】字符串左/右旋的本质,你真的认清了嘛?
【每天学一点系列~】这些内存函数你知道么?还记得么[\\doge]
【每天学一点系列~】一文带你彻底弄懂结构体大小和内存对齐

创作不易,给个三连呗亲!
在这里插入图片描述

以上是关于每天学一点系列~诡异的死循环的主要内容,如果未能解决你的问题,请参考以下文章

每天学一点系列~字符串左/右旋的本质,你真的认清了嘛?

每天学一点系列~看得见摸不着的“隐式类型转换”

每天学一点系列~这些内存函数你知道么?还记得么[doge]

每天学一点系列~一文带你彻底弄懂结构体大小和内存对齐

Python每天学一点之argparse

每天学一点 Kotlin -- 字符串和字符