前言:今天在做的题目之中 出现了一个十分有趣的现象 就是 使用memset中直接的问题。现在分享一下。
掉坑的题目 《1050 螺旋矩阵(25)(25 分)》
我们定义二维数组不过是三种方法
1.直接定义法 int P[100][100];
2.malloc定义法 int** P = (int **)malloc(sizeof(int *)*100); for(int i=0;i<100;i++) P[i]=(int *)malloc(sizeof(int)*100);
3.calloc 定义法 int** P = (int **)calloc(100,sizeof(int *)); for(int i=0;i<100;i++) P[i]=(int *)calloc(100,sizeof(int));
有的人说了 malloc不是大致和calloc相同吗? 但是有时候 一些细节就会让你 好久都没有办法查的出来。比如我今天所说的memset的超级大坑。
为了掉进我设下的这个坑 我们 使用方法 2 开辟了空间 创建了二维数组 。我们知道 使用malloc开辟的二维数组每一个元素的值就像在局部变量一样都是随机值。
这个时候 心大的同学就很想 使用 memset 来初始化这个“数组”了 在我们的印象里 我们初始化 使用 方法 1 定义的数组的时候都是这样的 (例如初始化为 0 ):memset(P,0,sizeof(P));
int P[100][100];
memset(P, 0, sizeof(P));
执行完成以后 通过编译器的调试框 我们可以看出 是初始化成功了
初始化前:
初始化后:
显然是成功的。
但是 但是 但是 。 我们使用方法 2 定义的“数组”再使用 这个方法的 话 就会掉进万丈深坑 !我们来看图
因为 不是 标准定义的数组 我们没法像上面这样直观的 表现出来 我们取 局部的图 来说明问题的所在。
因为只要开辟成功 那么 我读 P[0][0] 是不是应该是一个随机值。 对,我就要它读出随机值的图来分析 。
这个 就是执行memset之前的 P[0][0] 的情况 我们看到了 随机值。
然后我万恶的点击了单步。
结果就是这样的
WTF 读不出来了 但是 P[1][0]却能读出来 而且 并没有初始化 如图:
没有初始化我就不怪你了 还让我读不出来 ~~~ 什么破编译器 炸了算了。
但是我没有炸 我 把 P[0]和 NULL 做了一个比较
注意看我单步的黄色光标 我单步了哦 别看走眼
NULL NULL 我发现了什么 我发现了是 NULL 耶!从此学了一个新词 NULL 来 NULL 去 欢迎广大读友用来造句。哈哈
这样所有的谜题就解开了? 没有,因为 P[1]!=NULL 那这个又是怎么回事呢?
我们把目光投向那个 sizeof(P) 这里 按照我们正常的思维 我们猜一下 这个运算的结果是什么?答案是 4 !!
诶 我不是开了100的那个二维指针空间了吗?咋就是 4 了????而且这100个空间都是连续的啊!!
有些稀里糊涂的人马上就站出来 理直气壮的说 这个就是 4 没错啊,就同一般定义的二维数组一样啊 。不一样 我们看
是不是 4万 ??????? 说明了一般的数组是可以计算出数组 "连续" 空间的大小的 因为整数型 int 一个空间的大小是 4 ,100行100列一共有 100*100 == 10000个元素 所以 10000*4 == 40000 。
四...四万是么?刚刚看错了,对啊 就是 4万啊 。(你给我粗去~~马上立刻~ )
那么为什么 是 4 呢? 有的人又说了 那有可能是 sizeof(a[0]) ; 不对了啊~ 这个是 400 就不附图了 截图浪费时间啊
那么 4 从哪来 它又要到哪里去呢?????????? 总不能让他 NULL来NULL去吧!
然后我就试了一下这一组:
我们想一下 刚刚的P是不是一个二维的指针 那么这个4 是不是就是那个4了?
我回去看了一下 P的定义
啊~~~我尖叫了出来,手里的辣条 都忘记了 。
这这这这 ,这不是 变 变量吗 我不敢相信我的眼睛 于是我做了一个测试。
这下问题就彻底的暴露出来了
正经的解释开始:
1.P 无论怎样给它开空间 说到头 它就是一个变量 一个二维指针的变量,所以 用它计算空间的值自然就是 sizeof(空间的类型);
也就等同于sizeof(int**) 这个实验我们上面已经做过了 答案是 4
2.所以 我们 完全的了解了。
那么我们怎么解决初始化的问题呢 不会有是两个for吧 不是的啦 怎么这么 “土”呢?
我们还记得 calloc吗 用它来开辟的二维数组的空间默认就是初始化为 0 了呗 。
我们看下图
解决初始化问题。而且 嘿嘿~~
没有执行 if 它不再是一个NULL来NULL去的指针了~~
解决问题了。
忘记几个人真的好难啊!我好想回到大学以前 可是 又不能多想 因为现在自己的命运捏在自己手上,即使受伤也要 前进。