二维数组和二级指针

本文详细介绍了二维数组和二级指针的概念与应用。主要内容包括二维数组的内存存储方式、一维与二维数组间的转换、二级指针的定义及其在解决指针传值和传址调用问题中的作用。通过具体示例讲解了如何使用二级指针进行内存动态分配与释放。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

二维数组和二级指针

1.前言
  • 本文所用到的部分基础知识可以查看此文:
    http://blog.youkuaiyun.com/xingerr/article/details/72372563

  • 说明:

    1. 二维数组在内存中按照一维的方式进行存储
    2. 二维数组中的第一维是一维数组
    3. 二维数组中的第二维是具体的值
    4. 二维数组的数组名可以看做是常量指针
    5. array[2][4]根据选择不同可以为2行4列,也可以为4行2列
2.二维数组
  • 说明:

    1. 数组名代表数组首元素的地址
    2. 数组名可以看做指向数组的常量指针
    3. 可以看作为一维数组(在内存中存储都是线性一维的)
    4. 数组中的每个元素都是同类型的一维数组
    5. 数组定义时可以省略第一个的大小(系统自动计算),如:int a[][3];
  • 示例1:

int main()
{
    int a[5][5];  //定义二维数组
    //int (*p)[4];  //定义数组指针(指向4*4字节大小的数组)(也就是每次p+1地址向后走四个字节大小)
    int (*p)[5];  //定义数组指针(指向5*4字节大小的数组)

    p = a;  //将二维数组的数组名给数组指针p

    printf("%d\n", &p[4][2] - &a[4][2]);  //打印两个地址相减的结果,应该为0,(如果是4*4字节大小的结果为-4)
    return 0;
}
  • 示例2:
    void print(int a[], int n)
    {
        int i = 0;
        for(i = 0; i < n; ++i)
        {
            /*用一维方式遍历二维数组并打印*/
            printf("%d ", a[i]);
        }
        putchar(10);
    }

    int main()
    {
        int a[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
        int *p = &a[0][0];  //定义一级指针存放数组首元素的地址

        print(p, 9);

        /*------------------分割线----------------------*/

        int i = 0;
        int j = 0;

        for(i = 0; i < 3; ++i)
        {
             for(j = 0; j < 3; ++j)
             {
                /*正常双重循环打印数组*/
                /* 因为一维数组a[i] = *(a+i),同理二维a[i][j] = *(a[i] + j) = *(*(a + i) + j) */
                 printf("%d ", *(*(a + i) + j));
             }
        }
        putchar(10);

        return 0;
    }
  • 示例3:
int** Malloc(int row, int col)
{
    /*给二维数组申请动态空间,row为行数,col为列数*/

    int** ret = (int **)malloc(sizeof(int*) * row);
    /*定义二级指针ret,并申请row大小的空间,用来存放一级指针*/

    int* p = (int *)malloc(sizeof(int) * row * col);
    /*定义一级指针p,并申请大小为row*col的空间,存放每行的首地址*/

    int i = 0;
    if(ret && p)
    {
        /*对内存申请是否成功进行判断*/
         for(i = 0; i < row; ++i)
         {
            /*对每一行进行分配内存(p指向一维数组的首地址,每次取出相应的列数大小的字节给每一行)*/
             ret[i] = (p + col * i);
         }
    }
    else
    {
         free(ret);
         free(p);
         return NULL;
    }
    return ret;
}

void Free(int** a)
{
    /*释放内存*/
     free(a[0]);
     free(a);
}
3.二级指针
  • 说明:

    1. 因为指针变量会在内存中占用一定空间,所以可以定义指针保存指针变量的地址值
    2. 二级指针是解决指针的传值调用和传址调用的问题
  • 示例:

int reset(char** p, int size, int new_size)
{
    /*如果申请的内存没有使用完,则进行清空释放*/
    int ret = 1;
    int i = 0;
    int len = 0;
    char* pt = NULL;
    char* temp = NULL;
    char* pp = *p;  //定义一级指针pp接收二级指针p里面存放的指针的地址

    if((p != NULL) && (new_size > 0))
    {
         pt = (char *)malloc(new_size);  //申请一个新的空间(大小为前面申请内存使用过的大小)
         temp = pt;  //临时变量进行指针操作
         len = (size < new_size) ? size : new_size;
         /*三目运算符选取size和new_size两者较小的给len*/

         for(i = 0; i < len; ++i)
         {
            /*将以前申请的内存里的值进行复制到新的内存中*/
            *temp++ = *pp++;
         }
         /*释放以前的内存*/
         free(*p);
         *p = pt;  //返回新的内存地址
    }
    else
    {
         ret = 0;
    }
    return ret;
}

int main()
{
    char* p = (char*)malloc(5);  //动态申请内存大小为5的空间,地址给p

    printf("%0x\n", p);  //打印申请的内存空间的地址

    if(reset(&p, 5, 3))
    {
        /*将内存缩小为3个字节大小*/
        printf("%0x\n", p);  //打印新的内存空间的地址
    }

    return 0;
}
4.参考
  • 《C和指针》
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值