接上文,开始二维动态数组的学习。
这篇博客讲述了三个方法…真的脑洞大开
https://blog.youkuaiyun.com/qq_41822235/article/details/81142107
百度了很多方法,大多是这样的思路:不能像普通的二维数组同时分配行和列,要按维分配。
我就采用网上最常见的方法,用二维指针,也就是…指针的指针?
步骤一
1.先来补一波指针再说
2.一分钟过后自信的去看
C语言二级指针(指向指针的指针)详解
记录某个地址的指针自然在内存空间里有它的一席之地,自身也存在一个地址,指针的指针就是读取这个地址。
步骤二
梳理思路(来自某度):
1 定义二维指针。
2 确定数组维数,即行数和列数。
3 申请行数个一维指针大小空间,并赋值给二维指针。
4 对于每个一维指,申请列数个元素的空间,并赋值给对应的一维指针。
5 输入或赋值数据。
6 使用双重循环,逐个范围存储单元并输出。
7 逐个释放一维指针上的内存。
8 释放二维指针上的内存。
大致代码如下
#include <stdio.h> //包含输入输出函数
#include <stdlib.h>//包含动态内存分配函数。
int main()
{
int **p; //定义二维指针。
int m, n;//行数和列数。
int i,j;
scanf("%d%d", &m, &n); //输入行数和列数。
if(m <= 0 || n <= 0) return -1; //行数或列数非法。
p = (int **) malloc(sizeof(int *) *m);//申请一组一维指针空间。
for(i = 0; i < m; i ++)
p[i] = (int *)malloc(sizeof(int) * n); //对于每个一维指针,申请一行数据的空间。
for(i = 0; i < m; i ++)
for(j = 0; j < n; j ++)
scanf("%d",&p[i][j]);//输入第i行第j列的数据。其中&p[i][j]也可以写作p[i]+j或者是 *(p+i) + j. 功能相同。
printf("输入的数组为%d行%d列:\n", m, n);
for(i = 0; i < m; i ++)
{
for(j = 0; j < n; j ++)//这个循环可以输出一行元素。
printf("%d ", p[i][j]);//输出i行j列的元素。
printf("\n");//每行输入结束加换行符。
}
//释放内存
for(i = 0; i < m; i ++)
free(p[i]);
free(p);
return 0;
}
步骤三
拿出看不懂的地方
p = (int **) malloc(sizeof(int *) *m);//申请一组一维指针空间。
p[i] = (int *)malloc(sizeof(int) * n); //对于每个一维指针,申请一行数据的空间。
然后懵了,p[i]是?指针的指针这个数组是来自何方…
然后今日份感动:
问了zhou师兄,秒回,大赞
qq语音的翻译还是这么魔幻
hhh对了推一波他csdn博客,来看lrenez啊!以下是目前吃到的狗粮
百度他的名字,出来他和lrene
csdn有一位神秘博主,创号后只关注一人
甚至出的zjctf题目都
不说了
步骤四
开始补知识来填这个坑
理解和步骤是这样的:
1.指针的指针,实质还是指针,指向的仍是一个地址,所以不用管什么二维指针,N维指针指向的都是地址。
2.类似数组方面的知识。比如定义一个字符型二维数组str[10][10],那么如果我们要取出它第一行,就是 puts(str[0]),这里的str[0]已经是代表第一行的首地址了。
然后我对puts(a[i])进行了测试,竟然又涉及到了思路和pwn搭了一点点边的东西…下面是测试报告的博客(尴尬还没写完,写完会放到这里(点我,我写完了!),果然坑是可以无限延申的)
3.补充指针数组的知识
4.补充指向二维数组的指针知识
详细分析代码如下(写注释里面了):
#include <stdio.h>
int main(){
int a[3][4] = { {0, 1, 2, 3}, {4, 5, 6, 7}, {8, 9, 10, 11} };
int (*p)[4] = a;//理解前面的动态数组代码这步很关键
//因为*优先级低于[],所以加(),如果还是不懂可以看前面3.和4.里的超链接
//数组的类型为int [4],是a所包含的每个一维数组的类型。这句话有点没理解
//我的理解是一行就是一个一维数组,一行有四个,所以定义为4
printf("%d\n", sizeof(*(p+1)));
//最后输出来的是16,int类型占4,一行四个,4*4=16
//也就是*(p+1)实现了指针前进16字节,使得指针指向二维数组的下一行
//那么现在*(p+1)表示取地址上的数据,也就是整个第 1 行数据。
//注意是一行数据,是多个数据,不是第 1 行中的第 0 个元素
//因为它现在+1是有16个字节的长度,所以可以输出一行
return 0;
}
然后掌握了上面的知识,再来看这三行迷糊的代码
p = (int **) malloc(sizeof(int *) *m);
//申请一组一维指针空间。
for(i = 0; i < m; i ++)
p[i] = (int *)malloc(sizeof(int) * n);
//对于每个一维指针,申请一行数据的空间。
第一行代码这时候就比较清晰了,是定义了一个指针数组,也就是前面补充的第三点知识。
对下面的p[i]也能看懂了,无论是p[0]还是p[i]……p[m-1],里面的值都是指针
所以p[i] = (int *)malloc(sizeof(int) * n); 这句话就是对每一个指针都分配一个动态内存空间。也可以理解成为每一个指针开辟一个空间,然后把空间的首地址再给指针,简单明了。
步骤五
花了点时间做了一个脑图便于理解
如果看不清可以点这里(点我点我)
总结:简单的做了关于c语言第五章的习题,没想到居然把指针给搞懂了个七八成左右(果然在水杰 的任课下得靠自学吗……十二点没到,先去背英语了,祝我四级加油!!还能继续肝23333