Day7(上).二级指针实战
2015-06-21 15:25
211 查看
首先练习一下二级指针做函数参数的问题,题目在代码最前面。
在操作内存空间的时候,时刻要注意内存的分配和释放问题,必须要记住下面的初始化模版,做任何相关内存操作的项目,都必须首先在脑海中建立一个这样的初始化模型
———————————————————————————————————————————————————————————————————————————
下面是本节重点,有关二级指针做输出的问题。在学习完下面的内容之后,必须深刻理解这句话:
二级指针做函数参数(形参),在被调用函数里面修改实参。
如下是一个简单的例子,说明如何用一级指针去修改0级指针的值
下面看继续修改的结果代码,只修改int getmembuf函数体
总之,二级指针做函数参数(形参),在被调用函数里面修改实参。
———————————————————————————————————————————————————————————————————————————
二级指针做输出易犯错误
1.首先看第一个例子
2.show the codes
3.重复提及的二级指针做函数参数,在被调用函数里分配内存,并把结果甩出函数体。
看下面的代码对比
不多说了,不解释,自己看!!!二级指针做函数参数,在被调用函数里分配内存的精髓就是这两段代码!!!
4.结构体中的问题
看第一段代码
仔细观察如何将struct Teacher *createTeacher()替换成int createTeacher(struct Teacher **p)!!!
还不懂????继续延伸!!!!
一定要明白N级指针修改N-1级指针内存空间的方法!!!!!!
/******************************************************************************************************************* 题目:合并并排序两个指针数组,假如char *array1[] = { "bbbbb", "aaaaa", "ccccc", "22222", "11111", "44444" }, char array2[10][30] = { "zzzz", "yyyy", "xxxx" },合并输出{ "bbbbb", "aaaaa", "ccccc", "22222", "11111", "44444", "zzzz", "yyyy", "xxxx" },并按照从小到大/从大到小的顺序输出结果。 思路: 1.定义一个二级指针,用于保存结果 2.在排序函数体内,将题目中的两个指针数组合并,然后排序 3.输出结果,释放内存空间 函数: char **sortArray1Array2(char **pArray1, int nArray1Num, char(*pArray2)[30], int nArray2Num, int *nArray3Num) void free_arr(char ** arr, int length) 说明: 二级指针做函数参数;二级指针做函数参数把结果甩出来;怎么malloc怎么free *******************************************************************************************************************/ #define _CRT_SECURE_NO_WARNINGS #include "stdlib.h" #include "stdio.h" #include "string.h" //合并排序函数 char **sortArray1Array2(char **pArray1, int nArray1Num, char(*pArray2)[30], int nArray2Num, int *nArray3Num) { int i, j; //输出结果的长度 int length = nArray1Num + nArray2Num; //malloc输出结果的内存空间 char **pTmp = (char **)malloc((nArray1Num + nArray2Num)*sizeof(char *)); //一级指针分配内存 for (i = 0; i < length; i++) { pTmp[i] = (char *)malloc(sizeof(char) * 30); memset(pTmp[i], 0, sizeof(char) * 30); } //把第一个指针数组复制到输出指针数组 for (i = 0; i < nArray1Num; i++) { strcpy(pTmp[i], pArray1[i]); } //把第二个指针数组复制到输出指针数组 for (int k = 0; k < nArray2Num; k++, i++) { strcpy(pTmp[i], pArray2[k]); } //排序 for (i = 0; i < length; i++) { for (j = 0; j < length; j++) { if (strcmp(pTmp[i], pTmp[j]) > 0) { char tmp[30] = { 0 }; strcpy(tmp, pTmp[i]); strcpy(pTmp[i], pTmp[j]); strcpy(pTmp[j], tmp); } } } //把输出指针数组的长度甩出来 *nArray3Num = length; //返回输出结果指针数组 return pTmp; } void free_arr(char ** arr, int length) { int i; //判断形参是否为空 if (arr == NULL) { return; } //释放内存空间,记住一点,怎么malloc怎么free for (i = 0; i < length; i++) { if (arr[i] != NULL) free(arr[i]); } //判断每一个一级指针是否为空,不为空释放 if (arr[i] != NULL) { free(arr); } } void main() { int i; //输出指针数组,指针切记要初始化 char **pArray3 = NULL; int nArray3Num = 0; //要合并的两个指针数组 char *array1[] = { "bbbbb", "aaaaa", "ccccc", "22222", "11111", "44444" }; char array2[10][30] = { "zzzz", "yyyy", "xxxx" }; //合并排序 pArray3 = sortArray1Array2(array1, 6, array2, 3, &nArray3Num); //判断合并排序是否成功 if (pArray3 == NULL) { printf("func sortArray1Array2() err\n"); } //打印输出指针数组 for (i = 0; i < nArray3Num; i++) { printf("%s \n", pArray3[i]); } //释放内存空间 if (pArray3 != NULL) { free_arr(pArray3, nArray3Num); pArray3 = NULL; } system("pause"); }
在操作内存空间的时候,时刻要注意内存的分配和释放问题,必须要记住下面的初始化模版,做任何相关内存操作的项目,都必须首先在脑海中建立一个这样的初始化模型
/******************************************************************************************************************* 题目:合并并排序两个指针数组,假如char *array1[] = { "bbbbb", "aaaaa", "ccccc", "22222", "11111", "44444" }, char array2[10][30] = { "zzzz", "yyyy", "xxxx" },合并输出{ "bbbbb", "aaaaa", "ccccc", "22222", "11111", "44444", "zzzz", "yyyy", "xxxx" },并按照从小到大/从大到小的顺序输出结果。 思路: 1.定义一个二级指针,用于保存结果 2.在排序函数体内,将题目中的两个指针数组合并,然后排序 3.输出结果,释放内存空间 函数: char **sortArray1Array2(char **pArray1, int nArray1Num, char(*pArray2)[30], int nArray2Num, int *nArray3Num) void free_arr(char ** arr, int length) 说明: 二级指针做函数参数;二级指针做函数参数把结果甩出来;怎么malloc怎么free *******************************************************************************************************************/ #define _CRT_SECURE_NO_WARNINGS #include "stdlib.h" #include "stdio.h" #include "string.h" //合并排序函数 char **sortArray1Array2(char **pArray1, int nArray1Num, char(*pArray2)[30], int nArray2Num, int *nArray3Num) { int i, j; int length; //malloc输出结果的内存空间 char **pTmp = (char **)malloc((nArray1Num + nArray2Num)*sizeof(char *)); //一级指针分配内存 for (i = 0; i < length; i++) { pTmp[i] = (char *)malloc(sizeof(char) * 30); memset(pTmp[i], 0, sizeof(char) * 30); } /******************************************/ //返回输出结果指针数组 return pTmp; } void free_arr(char ** arr, int length) { int i; //判断形参是否为空 if (arr == NULL) { return; } //释放内存空间,记住一点,怎么malloc怎么free for (i = 0; i < length; i++) { if (arr[i] != NULL) free(arr[i]); } //判断每一个一级指针是否为空,不为空释放 if (arr[i] != NULL) { free(arr); } } void main() { int i; //输出指针数组,指针切记要初始化 char **pArray3 = NULL; int nArray3Num = 0; //要合并的两个指针数组 char *array1[] = { "bbbbb", "aaaaa", "ccccc", "22222", "11111", "44444" }; char array2[10][30] = { "zzzz", "yyyy", "xxxx" }; //合并排序 pArray3 = sortArray1Array2(array1, 6, array2, 3, &nArray3Num); //判断合并排序是否成功 if (pArray3 == NULL) { printf("func sortArray1Array2() err\n"); } /******************************************/ //释放内存空间 if (pArray3 != NULL) { free_arr(pArray3, nArray3Num); pArray3 = NULL; } system("pause"); }
———————————————————————————————————————————————————————————————————————————
下面是本节重点,有关二级指针做输出的问题。在学习完下面的内容之后,必须深刻理解这句话:
二级指针做函数参数(形参),在被调用函数里面修改实参。
如下是一个简单的例子,说明如何用一级指针去修改0级指针的值
#define _CRT_SECURE_NO_WARNINGS #include "stdlib.h" #include "stdio.h" #include "string.h" //用一级指针(通常是形参),去修改0级指针(通常是实参)的值 int getlen(int *p) { *p = 20; } void main() { int a; int *p = NULL; p = &a; //直接修改a的值 a = 1; //p是a的地址,*(a的地址)去间接修改a的值 *p = 10; //1级指针去修改0级指针的值 getlen(&a); printf("a:%d \n", a); system("pause"); }我们再深入一层,用二级指针去修改一级指针的值
#define _CRT_SECURE_NO_WARNINGS #include "stdlib.h" #include "stdio.h" #include "string.h" //用二级指针去修改一级指针的值 void main() { char *p = NULL; char ** p2 = NULL; //直接修改p的值 p = 0x11; printf("p:%x \n", p); //此处要理解&p的意义,即p成了和p2一样的“二级指针” p2 = &p; //*(p2)即为*(&p)=p,为了理解而这样解释 *(p2) = 0x22; printf("p:%x \n", p); system("pause"); }我们用函数体的形式实现上面的代码,在上面的形式上继续修改
#define _CRT_SECURE_NO_WARNINGS #include "stdlib.h" #include "stdio.h" #include "string.h" //用二级指针(通常是形参),去修改一级指针(通常是实参)的值 int getmembuf(char **p2) { //*(p2)即为*(&p)=p,为了理解而这样解释 *(p2) = 0x33; return 0; } void main() { char *p = NULL; char ** p2 = NULL; //直接修改p的值 p = 0x11; printf("p:%x \n", p); //此处要理解&p的意义,即p成了和p2一样的“二级指针” p2 = &p; //*(p2)即为*(&p)=p,为了理解而这样解释 *(p2) = 0x22; printf("p:%x \n", p); getmembuf(&p); printf("p:%x \n", p); system("pause"); }但是这样做的意义何在呢???为什么要这样用二级指针???
下面看继续修改的结果代码,只修改int getmembuf函数体
//用二级指针(通常是形参),去修改一级指针(通常是实参)的值 //相当于在被调用函数体内分配内存,把结果给甩出来 int getmembuf(char **p2) { //1.便于理解 //函数体内分配内存空间,使用二级指针将其甩出来 char **tmp; tmp = (char *)malloc(100); p2 = tmp; //2.实际项目这样写 p2 = (char *)malloc(100); return 0; }必须掌握上面的用法,二级指针做函数参数,函数体内分配内存,用二级指针把结果甩出来!!!!否则,C/C++的指针是白学的!!!!
总之,二级指针做函数参数(形参),在被调用函数里面修改实参。
———————————————————————————————————————————————————————————————————————————
二级指针做输出易犯错误
1.首先看第一个例子
#include "stdlib.h" #include "stdio.h" #include "string.h" int getmembuf(char **p) { char **tmp; tmp = (char *)malloc(100); *p = tmp; return 0; } void main() { char **p = NULL; getmembuf(p); system("pause"); }上面的例子,一执行就会down掉,为什么呢???我们来分析一下它的内存模型
2.show the codes
#include "stdlib.h" #include "stdio.h" #include "string.h" int getmembuf1(char **p) { char **tmp; tmp = (char *)malloc(100); tmp = "aaaaaaannnnnnnn"; *p = tmp; return 0; } void main() { //buf指针是一个const类型,无法修改 char buf[10]; //此处buf当作形参是错误的 getmembuf1(&buf); printf("%s", buf); if (buf != NULL) { free(buf); } system("pause"); }需要特别注意,二级指针做函数参数的时候,必须能够修改,即必须非const类型,上面代码的char buf[10]是无法修改内存地址的,切记!!!
3.重复提及的二级指针做函数参数,在被调用函数里分配内存,并把结果甩出函数体。
看下面的代码对比
void getmembuf(char *buf) { char * tmp; tmp = (char)malloc(100); buf = tmp; return; } void getmembuf(char **buf) { char ** tmp; tmp = (char*)malloc(100); buf = tmp; return; }
不多说了,不解释,自己看!!!二级指针做函数参数,在被调用函数里分配内存的精髓就是这两段代码!!!
4.结构体中的问题
看第一段代码
#include "stdlib.h" #include "stdio.h" #include "string.h" struct Teacher { char name[10]; int age; }; struct Teacher *createTeacher() { struct Teacher *tmp = NULL; tmp = (struct Teacher *)malloc(sizeof(struct Teacher)); return tmp; } void main() { struct Teacher *t1 = createTeacher(); if (t1 != NULL) { free(t1); } system("pause"); }看第二段代码
#include "stdlib.h" #include "stdio.h" #include "string.h" struct Teacher { char name[10]; int age; }; int createTeacher(struct Teacher **p) { //不要相信别人给你传的地址是可用的 if (p == NULL) return -1; struct Teacher *tmp = NULL; tmp = (struct Teacher *)malloc(sizeof(struct Teacher)); *p = tmp; return 0; } void main() { struct Teacher *t = NULL; createTeacher(&t); if (t != NULL) { free(t); } system("pause"); }
仔细观察如何将struct Teacher *createTeacher()替换成int createTeacher(struct Teacher **p)!!!
还不懂????继续延伸!!!!
#include "stdlib.h" #include "stdio.h" #include "string.h" int getmembuf(char ****p) { *p = 0x4; } void main() { char ****p1 = NULL; char *****p2 = NULL; //直接修改 p1 = 0x1; p1 = 0x2; //间接修改 p2 = &p1; *p2 = 0x3; printf("%d\n", p1); //间接修改2 getmembuf(&p1); printf("%d\n", p1); system("pause"); }
一定要明白N级指针修改N-1级指针内存空间的方法!!!!!!
相关文章推荐
- Java语言中的修饰符
- DWZ使用注意事项
- 四大自贸区的好处
- java final的使用
- navicat如何导入sql文件和导出sql文件
- Linux系统下 SVN 搭建(yum)安装
- 第十六周项目一--平方根的异常
- HDU Bone Collector(背包0/1)
- Tomcat中HttpServletResponse的实现类
- 读后感
- Java IO 之 File 的创建、重命名与遍历
- android LayoutInflater.inflate()的参数及其用法
- 【Android UI设计与开发】第10期:顶部标题栏(一)ActionBar详细概述和简单示例
- 改革春风吹满地(矢量的差乘)
- 实战部署weblogic集群及发布应用(2)
- java解析xml的几种方式
- leetcode(144):Binary Tree Preorder Traversal
- c++学习-虚函数
- singleton 线程安全的singleton
- 【Scala】模式匹配和样本类