Day7(上).二级指针实战

首先练习一下二级指针做函数参数的问题,题目在代码最前面。

/*******************************************************************************************************************
	题目:合并并排序两个指针数组,假如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级指针内存空间的方法!!!!!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值