【C 语言】多级指针 ( 在函数中生成 二级指针 | 通过传入的 三级指针 进行间接赋值 )

简介: 【C 语言】多级指针 ( 在函数中生成 二级指针 | 通过传入的 三级指针 进行间接赋值 )

文章目录

前言

一、在函数中生成 二级指针 ( 通过传入的 三级指针 进行间接赋值 )

二、完整代码示例

前言

如果要 通过 函数形参 间接赋值 修改 n nn 级指针, 需要向函数中传入 n + 1 n + 1n+1 级指针 形参 ;






一、在函数中生成 二级指针 ( 通过传入的 三级指针 进行间接赋值 )


通过 函数 形参变量 , 间接赋值 返回 生成的 二级指针 函数 ;


如果要生成一个 二级指针 , 必须传入 三级指针 , 才能修改 该 二级指针 ;



注意 : 传入的 三级指针 , 不要直接修改该值 , 先创建一个临时的 局部二级指针变量 , 将 二级指针 生成完毕后 , 最后再给 三级指针 指向的地址 进行赋值 ;



代码示例 :


/**
 * @brief 生成二维指针
 * @param num
 * @return
 */
int generate_memory(char ***p3, int num)
{
    // 循环控制变量
    int i = 0;
    // 声明二维指针
    char **p = NULL;
    // 在堆内存中 , 分配一块内存空间
    // 用于存储 num 个 一维指针
    // 每个 一维指针 指向一块内存空间
    p = (char **)malloc( sizeof(char*) * num );
    if(p == NULL)
    {
        return -1;
    }
    // 遍历 二维指针 指向的多个 一维指针
    // 并为每个 一维指针 在堆内存中 分配 20 字节内存
    for(i = 0; i < num; i++)
    {
        // 为每个字符分配 20 字节空间
        p[i] = (char *)malloc(sizeof (char) * 20);
        // 向内存中写入 字符串 , 字符串内容是 i + 1
        // 注意是通过通配符拼装的字符串
        sprintf(p[i], "%d", i + 1);
    }
    // 将 三维指针 指向 生成的 二维指针 地址
    *p3 = p;
    return 0;
}



二、完整代码示例


完整代码示例 :


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/**
 * @brief 生成二维指针
 * @param num
 * @return
 */
int generate_memory(char ***p3, int num)
{
    // 循环控制变量
    int i = 0;
    // 声明二维指针
    char **p = NULL;
    // 在堆内存中 , 分配一块内存空间
    // 用于存储 num 个 一维指针
    // 每个 一维指针 指向一块内存空间
    p = (char **)malloc( sizeof(char*) * num );
    if(p == NULL)
    {
        return -1;
    }
    // 遍历 二维指针 指向的多个 一维指针
    // 并为每个 一维指针 在堆内存中 分配 20 字节内存
    for(i = 0; i < num; i++)
    {
        // 为每个字符分配 20 字节空间
        p[i] = (char *)malloc(sizeof (char) * 20);
        // 向内存中写入 字符串 , 字符串内容是 i + 1
        // 注意是通过通配符拼装的字符串
        sprintf(p[i], "%d", i + 1);
    }
    // 将 三维指针 指向 生成的 二维指针 地址
    *p3 = p;
    return 0;
}
/**
 * @brief 打印二维指针数据
 * @param array
 * @param num
 */
void printf_array(char **array, int num)
{
    // 循环控制变量
    int i = 0;
    // 判定指针合法性
    if(array == NULL)
    {
        return;
    }
    // 打印字 二维指针 指向的 num 个 一维数组 指向的 字符串
    for(i = 0; i < num; i++)
    {
        printf("%s\n", array[i]);
    }
}
/**
 * @brief 二维指针排序
 * @param p
 * @param num
 * @return
 */
int sort_array(char **p, int num)
{
    // 循环控制变量
    int i = 0, j = 0;
    // 排序时 , 交换指针 , 该指针是存储 要 交换指针 的临时变量
    char *tmp = NULL;
    // 判定指针合法性
    if(p == NULL)
    {
        return -1;
    }
    // 对 二维指针 指向的数据进行排序
    for(i = 0; i < num; i++)
    {
        for(j = i + 1; j < num; j++)
        {
            // 交换 i , j 指针指向的内存数据
            // 从 大 到 小 进行排序
            if(strcmp(p[i], p[j]) < 0)
            {
                tmp = p[i];
                p[i] = p[j];
                p[j] = tmp;
            }
        }
    }
    return 0;
}
/**
 * @brief 释放二维指针内存
 * @param p
 * @param num
 */
void free_mem(char ***p3, int num){
    // 循环控制变量
    int i = 0;
    // 设置临时变量 , 接收 p3 指向的二维指针
    char **p = *p3;
    // 判定指针合法性
    if(p3 == NULL)
    {
        return;
    }
    // 释放内存
    // 先释放 num 个 一级指针
    for(i = 0; i < num; i++)
    {
        if(p[i] != NULL)
        {
            free(p[i]);
            p[i] = NULL;
        }
    }
    // 再释放 二级指针
    if(p != NULL)
    {
        free(p);
    }
    // 二维指针 置空
    *p3 = NULL;
}
/**
 * @brief 主函数入口
 * @return
 */
int main()
{
    // 二维指针 指向的 一维指针 个数
    int num = 4;
    // 声明二维指针
    char **p = NULL;
    // 循环控制变量
    int i = 0, j = 0;
    // 排序时 , 交换指针 , 该指针是存储 要 交换指针 的临时变量
    char *tmp = NULL;
    // 在堆内存中 , 分配一块内存空间
    // 用于存储 num 个 一维指针
    // 每个 一维指针 指向一块内存空间
    generate_memory(&p, num);
    // 打印字 二维指针 指向的 num 个 一维数组 指向的 字符串
    printf_array(p, num);
    // 对 二维指针 指向的数据进行排序
    sort_array(p, num);
    // 打印字 二维指针 指向的 num 个 一维数组 指向的 字符串
    printf("\nSort : \n");
    printf_array(p, num);
    // 释放内存
    free_mem(&p, num);
    // 命令行不要退出
    system("pause");
    return 0;
}


执行结果 :


image.png

目录
相关文章
|
缓存 监控 Linux
在Linux中,如何看当前系统有几颗物理CPU和每颗CPU的核数?
在Linux中,如何看当前系统有几颗物理CPU和每颗CPU的核数?
|
存储 Oracle Java
深入探索安卓应用开发:从环境搭建到第一个"Hello, World!"
本文旨在为安卓开发初学者提供一个清晰、简洁的入门指南。我们将一步步引导您完成安卓开发环境的搭建,并详细介绍如何创建您的第一个安卓应用程序。通过这篇文章,您不仅能够理解安卓应用开发的基本流程,还能掌握一些实用的技巧和方法,为进一步深入学习打下坚实的基础。
|
IDE Linux KVM
云计算|OpenStack|社区版OpenStack安装部署文档(十二--- openstack的网络模型解析---Rocky版)
云计算|OpenStack|社区版OpenStack安装部署文档(十二--- openstack的网络模型解析---Rocky版)
481 0
|
小程序 开发者
万能的微信小程序个人主页:商城系统个人主页、外卖系统个人主页、购票系统个人主页等等【全部源代码分享+页面效果展示+直接复制粘贴编译即可】
这篇文章分享了四个不同应用场景下的微信小程序个人主页的源代码和页面效果展示,包括商城系统、外卖系统、医疗挂号和电影购票系统的个人主页。提供了完整的页面布局和样式代码,允许开发者直接复制粘贴并根据自己的项目需求进行简单的改造使用。
万能的微信小程序个人主页:商城系统个人主页、外卖系统个人主页、购票系统个人主页等等【全部源代码分享+页面效果展示+直接复制粘贴编译即可】
|
Docker 容器
Docker 启动失败 (code=exited, status=1/FAILURE)错误解决办法
Docker 启动失败 (code=exited, status=1/FAILURE)错误解决办法
2629 1
|
存储 供应链 安全
web3.0知识扫盲
web3.0知识扫盲
545 0
|
网络协议 安全 数据挖掘
F5《企业DNS建设白皮书》中的DNS解析服务器最佳实践
F5《企业DNS建设白皮书》中的DNS解析服务器最佳实践
393 0
F5《企业DNS建设白皮书》中的DNS解析服务器最佳实践
|
存储 Cloud Native 数据挖掘
MinIO作为一种开源的对象存储系统,具有以下核心特点
MinIO作为一种开源的对象存储系统,具有以下核心特点
873 0
|
XML Java 数据格式
Spring-AOP @AspectJ语法基础
Spring-AOP @AspectJ语法基础
234 0
Jmeter之界面语言设置
Jmeter之汉化处理,中英文语言设置,临时性设置和永久汉化设置不同方式的介绍。。。
1148 0
Jmeter之界面语言设置