二级指针用法示例

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 ;
}

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;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-11-07 00:08:01

二级指针用法示例的相关文章

二级指针作为函数参数的典型用法

用二级指针作为函数参数,有两种典型情况:1.需要传递一级指针的数组时:例如标准C的main函数:int main(int argc, char*[] argv),数组最高维可以退化,char*[] argv等价于char** argv.这里argv代表命令行参数数组.2.需要对传入的一级指针进行修改时:例如:void alloc_new_char_array(int n, char** t){*t = (char*)malloc(n * sizeof(t));}这里可以通过返回值达到相同的效果,

OpenCV二维Mat数组(二级指针)在CUDA中的使用

CUDA用于并行计算非常方便,但是GPU与CPU之间的交互,比如传递参数等相对麻烦一些.在写CUDA核函数的时候形参往往会有很多个,动辄达到10-20个,如果能够在CPU中提前把数据组织好,比如使用二维数组,这样能够省去很多参数,在核函数中可以使用二维数组那样去取数据简化代码结构.当然使用二维数据会增加GPU内存的访问次数,不可避免会影响效率,这个不是今天讨论的重点了. 举两个代码栗子来说明二维数组在CUDA中的使用(亲测可用): 1. 普通二维数组示例: 输入:二维数组A(8行4列) 输出:二

黑马程序员---C基础9【字符串的输入输出】【字符串相关函数】【指针】【指针变量初始】【二级指针】

------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- [字符串的输入输出] 1.字符串输出: %s-------从给定的地址开始输出字符直到遇到\0停止: printf("%s\n",&a[3]);  printf("%s\n",a); char a[]="hellowo\0rd!"; 2.字符串输入: 从键盘上接收一个字符串,保存在以a为首地址的字符数组中 scanf("%s&

二级指针的问题汇总

二级指针的问题 如何在被调用函数里面新建数据,然后将数据的地址传递出来呢? 一般来说有两种方法,第一种思路是将数据的首地址以返回值的方法返回,第一种方法如下: #include <stdio.h> #include <stdlib.h> #include <string.h> char *newBuf(int num) { char *p; p = (char *)malloc(num * sizeof(char)); return p; } void deleteBu

关于二级指针的认识

在链表操作中经常会遇到链表头的问题,如下图: 在这个链表插入函数中,如果链表中第一个元素就小于newValue,则需要更新头指针.当然可以把头指针定义为全局变量,但这并不是最优解,所以我们需要在函数中更新头指针的值,如下图: 当然Link *head  这里的head就是struct ** Node二级指针,在这里只是实现了更新头指针的功能,其实二级指针还有更妙的用法:链表中每一个节点都有指向它的指针,指向头节点的是头指针,指向其他节点的是它前一个节点的链,这样只需要修改指向每个节点的链即可:

一级指针以及二级指针

我想不大理解二级指针的根源是我对程序对堆栈的用法还不够深入了解. 采用一级指针最好是方便修改指针对象的值,采用二级指针最好是方便修改指针的值. #include <iostream> #include <stdio.h> using namespace std; class haha { }; void main() { haha *p(new haha); printf("%p\n", p);//一级指针的地址 printf("%p\n",

从一级指针到二级指针

昨天,写了一些关于一级指针的见解,那么这次我们再来看看二级指针的一些用法,也可以说是我自己的一些见解 所谓二级指针其实和一级指针差不多,一级指针是存储0级指针地址的变量,(一定要记住这一点:指针也是变量,编译器会给它分配内存空间,它的内存空间和它指向的内存空间是不同的,它的内存空间里只能存储空间地址:)所以二级指针就是储存一级指针地址的变量,或者说二级指针是指向一级指针空间的变量:还可以说是指向一级指针的指针: 那么下面我们来看代码: void changePointer(char **c) {

二维数组和二级指针关系浅析

昨天写了关于一级指针的见解,即二级数组的用法和二级指针差不多,关于数组指针和指针数组这两个是不同的概念,这一点我们一定要清楚: 数组指针我们可以理解为指向数组的指针,就是一个指针: 指针数组则可以理解为数组里存的是指针,即每个储存空间上储存的是指针变量:这里储存了多个指针 一个数组可以这样定义 char a[3];分配了3个字节的内存 二维数组可以这样定义 char b[3][3];分配了3*3 即9个字节的内存 我们知道一维数组和一级指针的用法差不多,那么二级指针有和二级指针有什么关系呢? {

【转】Linus:利用二级指针删除单向链表

原文作者:陈皓 原文链接:http://coolshell.cn/articles/8990.html 感谢网友full_of_bull投递此文(注:此文最初发表在这个这里,我对原文后半段修改了许多,并加入了插图) Linus大婶在slashdot上回答一些编程爱好者的提问,其中一个人问他什么样的代码是他所喜好的,大婶表述了自己一些观点之后,举了一个指针的例子,解释了什么才是core low-level coding. 下面是Linus的教学原文及翻译—— “At the opposite en