二级指针用法示例

1、二级指针的第一种内存模型:指针数组

#include <stdlib.h>
#include <string.h>
#include <stdio.h>

void main21()    //不适用二级指针的常规做法
{
	int		i = 0, j = 0;
	int		num = 0;
	char	*tmp = NULL;
	//数组 数组中的每一个元素是指针 指针数组
	char *myArray[] = {"aaaaaa", "ccccc", "bbbbbb", "111111"};

	//打印
	num = sizeof(myArray)/sizeof(myArray[0]);

	printf("排序之前\n");
	for (i=0; i<num; i++)
	{
		//printf("%s \n", myArray[i]);
		printf("%s \n", *(myArray+i) );
	}

	//排序
	for (i=0; i<num; i++)
	{
		for (j=i; j<num; j++)
		{
			if (strcmp(myArray[i], myArray[j]) > 0 )
			{
				tmp = myArray[i];  //注意  交换的是数组元素 交换的是指针的值
				myArray[i] = myArray[j];
				myArray[j] = tmp;
			}
		}
	}

	printf("排序之后\n");
	for (i=0; i<num; i++)
	{
		//printf("%s \n", myArray[i]);
		printf("%s \n", *(myArray+i) );
	}

	printf("hello...\n");
	system("pause");
	return ;
}

void printMyArray11(char **myArray, int num)//数组中的每一个元素是指针(字符串常量的首地址),所以使用的是二级指针 
{
	int i = 0;
	for (i=0; i<num; i++)
	{
		//printf("%s \n", myArray[i]);
		printf("%s \n", *(myArray+i) );
	}
}

void sortMyArray11(char **myArray, int num)//数组中的每一个元素是指针(字符串常量的首地址) ,所以使用的是二级指针
{
	int i =0 , j = 0;
	char *tmp = NULL;
	//排序
	for (i=0; i<num; i++)
	{
		for (j=i; j<num; j++)
		{
			if (strcmp(myArray[i], myArray[j]) > 0 )
			{
				tmp = myArray[i];  //注意:交换的是数组元素(字符串常量的首地址),交换的是指针的值 
				                   //改变的是指针的指向
				myArray[i] = myArray[j];
				myArray[j] = tmp;
			}
		}
	}
}

void main()
{
	int		i = 0, j = 0;
	int		num = 0;
	char	*tmp = NULL;
	//数组 数组中的每一个元素是指针(字符串常量的首地址) 指针数组
	char *myArray[] = {"aaaaaa", "ccccc", "bbbbbb", "111111"};

	//打印
	num = sizeof(myArray)/sizeof(myArray[0]);

	printf("排序之前\n");
	printMyArray11(myArray, num);

	sortMyArray11(myArray, num);

	printf("排序之后\n");
	printMyArray11(myArray, num);

	printf("hello...\n");
	system("pause");
	return ;
}
二级指针用法示例_第1张图片

2、二级指针的第二种内存模型:二维数组

#include <stdlib.h>
#include <string.h>
#include <stdio.h>


//打印  排序 
//封装成函数
void main31()
{
	int i = 0, j = 0;
	int num = 4;
	char myBuf[30];
	char tmpBuf[30];
	char myArray[10][30] = {"aaaaaa", "ccccc", "bbbbbbb", "1111111111111"};

	//打印 
	printf("排序之前\n");
	for (i=0; i<num; i++)
	{
		printf("%s\n", myArray[i]);
	}

	for (i=0; i<num; i++)
	{
		for (j=i+1; j<num; j++)
		{
			if (strcmp (myArray[i],  myArray[j]) > 0)
			{
				strcpy(tmpBuf, myArray[i]);  //交换的是内存块
				strcpy(myArray[i], myArray[j]);
				strcpy(myArray[j], tmpBuf);
			}
		}
	}

	//打印 
	printf("排序之后\n");
	for (i=0; i<num; i++)
	{
		printf("%s\n", myArray[i]);
	}


	printf("hello...\n");
	system("pause");
	return ;
}

//问题的本质是:dm03_二级指针做输入_第2种内存模型(二维数组) 的 myArray + 1
             // dm03_二级指针做输入_第1种内存模型(指针数组)   myArray + 1 不一样 ;
//指针的步长不一样  指针所指向的内存空间的数据类不一样 。
void printMyArray02_err(char **myArray, int num)//错误打印模型,涉及到多维数组退化为指针的细节
{
	int i = 0;
	for (i=0; i<num; i++)
	{
		//printf("%s \n", myArray[i]);
		printf("%s \n", *(myArray+i) );  //见问题本质
	}
}

void printMyArray02(char myArray[10][30], int num)//正确打印模型
{
	int i = 0;
	for (i=0; i<num; i++)
	{
		//printf("%s \n", myArray[i]);
		printf("%s \n", *(myArray+i) );  //见问题本质
	}
}

//交换的是内存块!
void sortMyArray02(char myArray[10][30], int num)
{
	int i, j = 0;
	char tmpBuf[30];

	for (i=0; i<num; i++)
	{
		for (j=i+1; j<num; j++)
		{
			if (strcmp (myArray[i],  myArray[j]) > 0)
			{
				strcpy(tmpBuf, myArray[i]);  //交换的是内存块
				strcpy(myArray[i], myArray[j]);
				strcpy(myArray[j], tmpBuf);
			}
		}
	}

}

//打印  排序 
//封装成函数
void main333()
{
	int i = 0, j = 0;
	int num = 4;
	char myBuf[30];
	char tmpBuf[30];
	char myArray[10][30] = {"aaaaaa", "ccccc", "bbbbbbb", "1111111111111"};

	//myarray:编译器只会关心:有10行 ,每行30列。目的是:
	//myarray+1:多维数组名的本质,+1以后步长是多少,跳30个单元!
	{
		int len1 = sizeof(myarray);   // 300
		int len2 = sizeof(myarray[0]);//30 
		int size = len1/len2;         //10 ,实际上求出来的是多少行,和一维对比
		printf("len1:%d , len2:%d , size:%d \n", len1, len2, size);
	}	

	//打印 
	printf("排序之前\n");
	printMyArray02(myArray, num);
	
	sortMyArray02(myArray, num);

	//打印 
	printf("排序之后\n");
	printMyArray02(myArray, num);

	printf("hello...\n");
	system("pause");
	return ;
}

3、二级指针的第三种内存模型:扔开C编译器,手工打造二维内存
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

//直接写
void main41()
{
	int i = 0, j = 0;
	char **p2 = NULL;
	int num = 5;
	char *tmp = NULL;//辅助下面交换指针
	char tmpbuf[100];//辅助下面交换内存
	
	//自己打造内存
	p2 = (char **)malloc(sizeof(char *) * num);//char **里面装char *
	for (i=0; i<num; i++)
	{
		p2[i] = (char *)malloc(sizeof(char)  * 100  ); //char buf[100];       //char *里面装char数据
		sprintf(p2[i], "%d%d%d", i+1, i+1, i+1);       //以"%d%d%d"的格式打印字符串到p2
	}

	//排序之前 
	printf("排序之前:\n");
	for (i=0; i<num; i++)
	{
		printf("%s \n", p2[i]);
	}

	//排序 交换的是:指针
	/*
	for (i=0; i<num; i++)
	{
		for (j=i+1; j<num; j++)
		{
			if (strcmp( p2[i] , p2[j]) < 0)
			{
				tmp = p2[i];
				p2[i] = p2[j];
				p2[j] = tmp;
			}
		}
	}
	*/

	//排序 交换的是:内存
	for (i=0; i<num; i++)
	{
		for (j=i+1; j<num; j++)
		{
			if (strcmp( p2[i] , p2[j]) < 0)
			{
				strcpy(tmpbuf, p2[i]);
				strcpy( p2[i], p2[j]);
				strcpy( p2[j], tmpbuf);
			}
		}
	}
	
	//排序之后 
	printf("排序之后:\n");
	for (i=0; i<num; i++)
	{
		printf("%s \n", p2[i]);
	}

	//释放内存
	for(i=0; i<num; i++)
	{
		if (p2[i] != NULL)
		{
			free(p2[i]);
			p2[i] = NULL;
		}
	}
	if (p2!=NULL) 
	{
		free(p2);
	}

	printf("hello...\n");
	system("pause");
	return ;
}

//改写、封装
//分配内存
char **getMem41(int num)
{
	int i = 0;
	char **p2 = NULL;
	p2 = (char **)malloc(sizeof(char *) * num);
	if (p2 == NULL)
	{
		return NULL;
	}

	for (i=0; i<num; i++)
	{
		p2[i] = (char *)malloc(sizeof(char)  * 100  ); //char buf[100];
		sprintf(p2[i], "%d%d%d", i+1, i+1, i+1);
	}
	return p2;
}

//打印
void printMyArray03(char **myArray, int num)    //二级指针
{
	int i = 0;
	for (i=0; i<num; i++)
	{
		//printf("%s \n", myArray[i]);
		printf("%s \n", *(myArray+i) );
	}
}

//排序
void sortMyArray03(char **myArray, int num)     //二级指针
{
	int i =0 , j = 0;
	char *tmp = NULL;
	//排序
	for (i=0; i<num; i++)
	{
		for (j=i; j<num; j++)
		{
			if (strcmp(myArray[i], myArray[j]) > 0 )
			{
				tmp = myArray[i];  //注意  交换的是数组元素 交换的是指针的值 //改变指针的指向
				myArray[i] = myArray[j];
				myArray[j] = tmp;
			}
		}
	}
}

//释放内存
void getMem41_Free(char **p2, int num)    //二级指针
{
	int i = 0;
	//释放内存
	for(i=0; i<num; i++)
	{
		if (p2[i] != NULL)
		{
			free(p2[i]);
			p2[i] = NULL;
		}
	}
	if (p2!=NULL) 
	{
		free(p2);
	}

}

void main()
{
	int i = 0, j = 0;
	char **p2 = NULL;
	int num = 5;
	char *tmp = NULL;
	char tmpbuf[100];
	p2 = getMem41(num);

	//排序之前 
	printf("排序之前\n");
	printMyArray03(p2, num);

	sortMyArray03(p2, num);

	//排序之前 
	printf("排序之后\n");
	printMyArray03(p2, num);

	getMem41_Free(p2,  num); //p2是一个野指针
	return ;
}

4、总览二级指针的三种内存模型:

#define  _CRT_SECURE_NO_WARNINGS 
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

void main2()
{
	int i = 0;

	//指针数组
	char *   p1[] = {"123", "456", "789"};

	//二维数组
	char p2[3][4]  = {"123", "456", "789"};

	//手工二维内存
	char **p3 = (char **)malloc(3 * sizeof(char *)); //int array[3];
	for (i=0; i<3; i++)
	{
		p3[i] = (char *)malloc(10*sizeof(char)); //char buf[10]
		sprintf(p3[i], "%d%d%d", i, i, i);
	}
}

5、三种内存模型综合演练:

/*
int sort(char *p[], int count, char **p, int *ncount);
int sort(char *p[], int count, char(*p)[30], int *ncount);
int sort(char(*p)[30], int ncount, char **p, int *ncount);

//把第一种内存模型和第二种内存模型结果copy到第三种内存模型中,并排序、打印
char **sort(char **p1, int num1, char(*p)[30], int num2, int *num3);
*/

#include"stdio.h"
#include"stdlib.h"
#include"string.h"

int sort(char **myp1, int num1, char (*myp2)[30], int num2, int ***myp3, int *num3)
{
	int i = 0, j = 0, k = 0;
	int tmplen = 0;
	char *tmpP = NULL;//辅助指针变量,以便排序使用

	//分配内存,以供拷贝
	char **p3 = NULL;
	p3 = (char **)malloc((num1 + num2)*sizeof(char *));  //里面装的是指针
	if (p3 == NULL)
	{
		return -1;
	}

	//拷贝
	for (i = 0; i < num1; i++)
	{
		tmplen = strlen(myp1[i]) + 1;
		p3[i] = (char *)malloc(tmplen *sizeof(char));//挂内存,指向内存空间
		if (p3[i] == NULL)
		{
			return -2;
		}
		strcpy(p3[i], myp1[i]);//赋值,拷贝
	}
	for (j = 0; j < num2; j++, i++)
	{
		tmplen = strlen(myp2[j]) + 1;
		p3[i] = (char*)malloc(tmplen*sizeof(char));//挂内存,指向内存空间
		if (p3[i] == NULL)
		{
			return -3;
		}
		strcpy(p3[i], myp2[j]);//赋值,拷贝
	}

	//排序
	tmplen = num1 + num2;
	for (i = 0; i < tmplen; i++)
	{
		for (j = i + 1; j < tmplen; j++)
		{
			if (strcmp(p3[i], p3[j])>0)
			{
				tmpP = p3[i];
				p3[i] = p3[j];
				p3[j] = tmpP;
			}
		}
	}

	//间接赋值
	*num3 = tmplen;
	*myp3 = p3;

	return 0;
}

void sortFree1(char **p, int len)//第一种释放内存方法,仅释放内存
{
	int i = 0;
	if (p == NULL)
	{
		return;
	}
	for (i = 0; i < len; i++)
	{
		free(p[i]);
	}
	free(p);
}

void sortFree2(char ***myp, int len)//第二种释放内存的方法,把二级指针指向的二维内存释放掉的同时间接地修改了实参的值
{
	int i = 0;
	char **p = NULL;
	if (myp == NULL)
	{
		return;
	}

	p = *myp; //还原成二级指针
	if (p == NULL)
	{
		return;
	}
	for (i = 0; i < len; i++)
	{
		free(p[i]);
	}
	free(p);
	*myp = NULL;    //myp是实参的地址     //间接赋值是指针存在的最大意义
}

int main()
{
	int ret = 0;
	char *p1[] = { "aaaa", "ssssss", "dddddd" };//指针数组
	char buf2[10][30] = { "11111", "2222", "33333333" };//二维数组
	char **p3 = NULL;
	int len1, len2, len3;

	len1 = sizeof(p1) / sizeof(*p1);
	len2 = 3;

	ret = sort(p1, len1, buf2, len2, &p3, &len3);
	if (ret != 0)
	{
		printf("func sort() err!");
	}

	for (int i = 0; i < len3; i++)
	{
		printf("%s\n", p3[i]);
	}

	//sortFree1(p3, len3);
	sortFree2(&p3, len3);//释放内存

	return ret;
}

你可能感兴趣的:(C语言,二级指针)