从题目入门指针和动态一二维数组的历程(萌新入门可参考)(下篇)

接上文,开始二维动态数组的学习。
这篇博客讲述了三个方法…真的脑洞大开
https://blog.csdn.net/qq_41822235/article/details/81142107
百度了很多方法,大多是这样的思路:不能像普通的二维数组同时分配行和列,要按维分配。
我就采用网上最常见的方法,用二维指针,也就是…指针的指针?

步骤一

1.先来补一波指针再说

C语言指针是什么?1分钟彻底理解C语言指针的概念

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

猜你喜欢

转载自blog.csdn.net/zjjcxy_long/article/details/103112318