【C 语言】二级指针内存模型 ( 指针数组 | 二维数组 | 自定义二级指针 | 将 一、二 模型数据拷贝到 三 模型中 并 排序 )
2023-06-13 09:18:00 时间
文章目录
一、指针数组 和 二维数组 数据 拷贝到 自定义二级指针 中
将 指针数组 和 二维数组 中的数据 拷贝到 自定义二级指针 内存模型中 , 并进行排序 ;
1、函数形参 设计规则
函数形参 设计规则 : 向 函数中 传入 二级指针 , 如果只是 使用 该 二级指针 指向的数据 , 可以 直接传入 二级指针 作为形参 ; 如果 需要 修改 二级指针 的指向 , 则需要 传入 三级指针 ;
2、三种内存模型 对应 函数形参 指针退化规则
① 指针数组 : 指针数组 参数 , 外层是数组 , 内层是指针 , 外层数组 退化成 指针 , 整体退化成 二级指针 ;
// 指针数组
char *p1[] = {"ab", "ef", "cd"};
退化为 :二级指针 ;
char **p1
② 二维数组 : 二维数组 , 最高维退化成 指针 , 整体退化成 数组指针 , 指向数组的指针 ;
// 二维数组
char p2[3][5] = {"13", "35", "22"};
退化为 : 数组指针 ;
// 数组指针
char (*p2)[5]
③ 二维指针 : 二维指针 作为参数 不退化 ;
// 二级指针
char **p3 = NULL;
退化为 :
// 二维指针
char **p3
代码示例 :
/**
* @brief copy_data 将 指针数组 和 二维数组 中的数据拷贝到 二维指针 中
* @param p1 指针数组 参数 , 外层是数组 , 内层是指针 , 外层数组 退化成 指针 , 整体退化成 二级指针
* @param count1 指针数组 中的 指针变量元素个数
* @param p2 二维数组 , 最高维退化成 指针 , 整体退化成 数组指针 , 指向数组的指针
* @param count2 二维数组的 一维数组 个数
* @param newp 指向 二级指针 的 三级指针
* @param count3p 指向一个数字的指针 , 该 数字是 二级指针 指向的 一级指针 个数
* @return
*/
int copy_data(char **p1, int count1, char (*p2)[5], int count2, char ***newp, int *count3p)
二、完整代码示例
完整代码示例 :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* 计算数组 array 大小 */
#define LENGTH(array) (sizeof(array)/sizeof(*array))
/**
* @brief copy_data 将 指针数组 和 二维数组 中的数据拷贝到 二维指针 中
* @param p1 指针数组 参数 , 外层是数组 , 内层是指针 , 外层数组 退化成 指针 , 整体退化成 二级指针
* @param count1 指针数组 中的 指针变量元素个数
* @param p2 二维数组 , 最高维退化成 指针 , 整体退化成 数组指针 , 指向数组的指针
* @param count2 二维数组的 一维数组 个数
* @param newp 指向 二级指针 的 三级指针
* @param count3p 指向一个数字的指针 , 该 数字是 二级指针 指向的 一级指针 个数
* @return
*/
int copy_data(char **p1, int count1, char (*p2)[5], int count2, char ***newp, int *count3p)
{
// 返回值
int ret = 0;
// 循环控制变量
int i = 0, j = 0;
// 临时长度
int len = 0;
// 创建的新的 二级指针 , 用于存放 指针数组 二维指针 中的数据
char **p3 = NULL;
// 分配一块内存 , 这块内存中存放 count1 + count2 个一级指针
p3 = (char **)malloc((count1 + count2) * sizeof(char *));
// 验证指针合法性
if (p3 == NULL)
{
ret = -1;
return ret;
}
// 遍历将 p1 指针数组 中的数据 拷贝到 二级指针 中
for (i = 0; i < count1; i++)
{
// 指针数组 中指针 指向的 字符串长度
// 最后的 + 1 是加上 \0 字符
len = strlen(p1[i]) + 1;
// 为 指向字符串的 一级指针 在堆内存中分配内存
p3[i] = (char *)malloc( len * sizeof(char)) ;
// 如果堆内存分配失败 , 直接退出
if (p3[i] == NULL)
{
return -2;
}
// 向堆内存中拷贝 字符串 数据
strcpy(p3[i], p1[i]);
}
// 遍历将 p2 二维数组 中的数据 拷贝到 二级指针 中
// 之前已经拷贝了 count1 个 , 因此从第 count1 + 1 位置开始拷贝
// 第 count1 + 1 个的索引从 0 开始 , 其索引是 count1 ;
for (j = 0; j < count2; j++)
{
// 计算 二维数组 中第 j 个一维数组 字符串长度
// 最后的 + 1 是加上 \0 字符
len = strlen(p2[j]) + 1;
// 为 指向字符串的 一级指针 在堆内存中分配内存
p3[count1 + j] = (char *)malloc(len * sizeof(char));
// 堆内存分配失败 , 退出
if (p3[count1 + j] == NULL)
{
return -3;
}
// 向堆内存中拷贝 字符串 数据
strcpy(p3[count1 + j], p2[j]);
}
// p3 二维指针 中存储的 字符串个数
len = count1 + count2;
// 指针 间接赋值 作为 返回值
*count3p = len; // 二维指针 赋值给 三维指针形参 指向的内存地址
*newp = p3; // 字符串个数 赋值
return 0;
}
/**
* @brief sort_data 二级指针 指向的 一级指针 数据排序
* 需要修改 二级指针 指向的一级指针次序
* 二级指针 不需要修改 , 因此这里传入 二级指针即可
* 如果需要修改 二级指针 , 则需要传入 三级指针
* @param p3 二级指针 数据
* @param num3 二级指针 指向的 一级指针 个数
* @return
*/
int sort_data(char **p3, int len)
{
// 循环控制变量
int i = 0, j = 0;
// 交换 字符串 时的临时变量
char *p = NULL;
// 验证指针合法性
if(p3 == NULL)
{
return -1;
}
// p3 指向的 若干 字符串 之间的排序
for (i = 0; i < len; i++)
{
for (j = i + 1; j < len; j++)
{
if ( strcmp(p3[i], p3[j]) > 0 )
{
// 交换 i, j 位置的 一级指针
p = p3[i];
p3[i] = p3[j];
p3[j] = p;
}
}
}
return 0;
}
/**
* @brief sort_data 二级指针 指向的 一级指针 数据排序
* 需要修改 二级指针 指向的一级指针次序
* 二级指针 不需要修改 , 因此这里传入 二级指针即可
* 如果需要修改 二级指针 , 则需要传入 三级指针
* @param p3 二级指针 数据
* @param num3 二级指针 指向的 一级指针 个数
* @return
*/
int print_data(char **p3, int len)
{
// 循环控制变量
int i = 0;
// 交换 字符串 时的临时变量
char *p = NULL;
// 验证指针合法性
if(p3 == NULL)
{
return -1;
}
// p3 指向的 若干 字符串 之间的排序
for (i = 0; i < len; i++)
{
printf("%s\n", p3[i]);
}
return 0;
}
/**
* @brief 主函数入口
* @return
*/
int main(int argc, char* argv[], char**env)
{
// 指针数组
char *p1[] = {"ab", "ef", "cd"};
// 二维数组
char p2[3][5] = {"13", "35", "22"};
// 二级指针
char **p3 = NULL;
// 存储 p3 指向的一级指针个数
int len3 = 0;
// 将 指针数组 二维数组 数据 拷贝到 二级指针 中
copy_data(p1, 3, p2, 3, &p3, &len3);
// 拷贝之后的结果
print_data(p3, len3);
// 数据排序
sort_data(p3, len3);
// 打印排序之后的结果
printf("\nSort :\n");
print_data(p3, len3);
// 命令行不要退出
system("pause");
return 0;
}
执行结果 :
ab
ef
cd
13
35
22
Sort :
13
22
35
ab
cd
ef
请按任意键继续. . .
相关文章
- JVM内存分配与管理详解
- 内存泄漏该如何解决?
- 100亿参数的语言模型跑不动?MIT华人博士提出SmoothQuant量化,内存需求直降一半,速度提升1.56倍!
- 【C++ 语言】C++字符串 ( string 类 | 创建方法 | 控制台输出 | 字符串操作 | 栈内存字符串对象 | string* )
- 【C++ 语言】智能指针 引入 ( 内存泄漏 | 智能指针简介 | 简单示例 )
- 【C 语言】内存四区原理 ( 栈内存属性增长方向 | 栈内存开口方向 | 代码示例 )
- 【错误记录】C 语言中通过指针操作字符串常量出错记录 ( 只有 栈内存 或 堆内存 中的数据才能通过指针修改 | 不要通过指针修改常量区的字符串 )
- 【C 语言】二级指针作为输入 ( 自定义二级指针内存 | 二级指针 排序 | 通过 交换指针方式 进行排序 )
- 【C 语言】二级指针作为输入 ( 自定义二级指针内存 | 二级指针排序 | 抽象业务逻辑函数 )
- 【C 语言】二级指针案例 ( 多级指针内存释放问题 | 多级指针避免野指针 )
- 【C 语言】结构体 ( 结构体类型定义 | 结构体类型别名 | 声明结构体变量的三种方法 | 栈内存中声明结构体变量 | 定义隐式结构体时声明变量 | 定义普通结构体时声明变量 )
- 【C 语言】结构体 ( 结构体变量内存操作 | 通过 “ . “ 操作符操作结构体内存空间 | 通过 “ -> “ 操作符操作结构体内存空间 )
- 【C 语言】结构体 ( 结构体 数组 作为函数参数 | 数组 在 栈内存创建 )
- 精通Linux交换内存管理(linuxswap内存)
- 内存占用Linux下检查Redis内存使用量(linux查看redis)
- Linux查看内存使用情况的命令(linux看内存命令)
- 使用内存借助Linux限制进程最大内存使用(linux限制进程)
- MySQL中的内存管理与优化(内存与mysql)
- Redis:基于内存的高性能数据库(redis内存数据库)
- 基于Redis的内存数据库存储技术(redis内存数据库)
- Oracle数据库内存优化提升系统性能(oracle内存调大)
- redis多少容量打开新世界大门(一台redis内存多大)
- 策略Redis默认内存淘汰策略改变你的理解(redis 默认内存淘汰)
- 访问php时提示内存位置访问无效的解决办法和思路分析