二重指针(即指向指针的指针)的应用场景

以下内容源于日常学习的总结与整理,欢迎交流。 

参考博客

(1)值传递与地址传递的区别_天糊土的博客-CSDN博客

(2)二维数组数和指针操作的理解_天糊土的博客-CSDN博客

(3)“指针+1”的理解_天糊土的博客-CSDN博客

(4)多重指针操作_天糊土的博客-CSDN博客_多重指针

实际编程中,二重指针主要有以下应用场景,或者说用法。

(1)用“指向指针的指针”,来指向指针数组。

比如下面例子中,二重指针p,指向了指针数组a。 

//用二重指针指向指针数组

#include<stdio.h> 
int change(char **p)//此函数将每个字符串的字符都改成‘c’
{
	int i, j;
	for (i = 0; i < 5; i++)
	{
		for (j = 0; *(*(p + i) + j) != '\0'; j++)
		{
			*(*(p + i) + j) = 'c';
			printf("%c", *(*(p + i) + j));
		}
		printf("\n");
	}
	return 0;
}

int main(void)
{
	char *a[5] = { "hello", "zhuyu", "jiajia", "linux","Ubuntu" };
	change(a);//这里的a是数组的字母,它表示a[0]的地址,则*a表示a[0]
              //而a[0]是字符指针,*a[0]才表示字符串“hello”中的第一个字符‘h’
	return 0;
}

(2)用“指向指针的指针”,来取得二维数组的元素。

/*
#include<stdio.h

//错误的做法
int change(char **p)
{
	int i, j;
	for (i = 0; i < 5; i++)
	{
		for (j = 0; *(*(p + i) + j) != '\0'; j++)
		{
			printf("%c", *(*(p + i) + j));
		}
		printf("\n");
	}
	return 0;
}

//若希望赋值,则不能使用指针的指针,要使用数组进行运算。
int change(char p[][10])
{
   int i, j;
   for (i = 0; i < 5; i++)
   {
     for (j = 0; p[i][j] != '\0'; j++)
     {
        p[i][j] = 'c';
        printf("%c", p[i][j]);
     }
     printf("\n");
   }
   return 0;
}

int main(void)
{
	char a[5][10] = { "hello", "zhuyu", "jiajia", "linux","Ubuntu" };
	change(a);
	return 0;
}

*/


#include<stdio.h> 
int change(char **p)
{
	int i, j;
	for (i = 0; i < 5; i++)
	{
		for (j = 0; *(*(p + i) + j) != '\0'; j++)
		{
			*(*(p + i) + j) = 'c';
			printf("%c", *(*(p + i) + j));
		}
		printf("\n");
	}
	return 0;
}

int main(void)
{
	char a[5][10] = { "hello", "zhuyu", "jiajia", "linux","Ubuntu" };
	char *b[5] = { a[0],a[1],a[2],a[3],a[4] };//这样做读取和写入操作都是可以的。
	change(b);
	return 0;
}

(3)用“指向指针的指针”,在子函数中修改主函数传过来的指针的指向。

比如主函数申明一个指针变量,且不为其分配指向空间(只是指向NULL),然后取该指针变量的地址传参给子函数;然后在子函数里根据需要申请一片空间;对传参解引用后得到原来的指针变量,且把该指针变量指向刚才申请的空间(修改了原来指针的指向,这是本质);从而实现不确定返回值个数的编程方法(这是应用)。

例子1:

#include<stdio.h>
int find(char *s, char src, char **rt)//从s中查询出src字符所在的位置并在rt中返回。
{
	int i = 0;
	while (*(s + i))
	{
		if (*(s + i) == src)//只会出现一次满足条件,此时将此地址给*rt,即p
		{
			* rt = s + i;//这里修改了p的指向
		}
		i++;
	}
	return 0;
 }


int main(void)
{
   char a[10] = "zhuyujia";
   char *p=NULL;
   find(a, 'y', &p);//改变p的指向,在子函数中实现
   printf("%s", p);
   getchar(); getchar();
   return 0;
}

/*
//补充:
打印指针的时候,会把指针所指向的内容以及至字符串末位的内容都打印出来
#include<stdio.h>
int main(void)
{
	char a[10] = "abcdefgff";
	char* p = &a[6];
	printf("%s", p);//会打印gff
	getchar(); getchar();
	return 0;
}
*/

例子2: 

#include <stdlib.h>
#include <time.h>
#include<stdio.h>
/*当然有必须使用二级指针才能解决的情况,如,某个函数的功能是
返回某个问题的计算结果,但是结果数据是不确定个数的值,所以
在调用此函数时不知道事先应分配多少空间来保存返回的数据,此时
的处理办法就是传递一个没有分配空间的指针的指针(地址)进去,
让函数自己根据计算的结果分配足够的空间来保存结果,并返回,
调用者使用了结果后,由调用者负责内存的释放,即,大家可能听说
过的"谁使用(调用)谁释放"之类的话,如下面的代码:*/

//返回不定结果个数的计算函数
//参数int **pResult  保存返回数据的指针的指针
//参数int &count     保存返回的结果个数
void Compute2(int **pResult, int &count)
{
	//使用随机数来模拟计算结果数的个数
	srand(time(NULL));
	count = rand() % 10;//控制个数在10个以内

	*pResult = new int[count];//*pResult相当于主函数传来的pResult指针,
							  //这里就修改了主函数中的pResult指向,因为还是
                              //指针,因此可以指向新开辟的空间
	for (int i = 0; i < count; i++)
	{
		(*pResult)[i] = rand();//给结果随即赋值
	}
}

//返回不定结果个数的计算函数(此函数不能返回数据)
//参数int *pResult   为保存返回数据的指针
//参数int &count     为保存返回的结果个数
void Compute1(int *pResult, int &count)
{
	//使用随机数来模拟计算结果数的个数
	srand(time(NULL));
	count = rand() % 10;//控制个数在10个以内

	pResult = new int[count];
	for (int i = 0; i < count; i++)
	{
		pResult[i] = rand();//给结果随即赋值
	}
}

int main(void)
{
	int *pResult = NULL;
    //待获取结果的指针,这里没有分配空间大小,因为不知道返回结果的个数
    //具体返回的个数在在子函数中确定,此时指针pResult指向也改变了
    //这就间接的说明“在子函数中修改主函数传来的指针”的意图
    //具体的应用就在于返回个数不确定的场景,这是后面编程的一个体会点

	int count = 0;//返回结果的个数

	 /*
	  Compute1(pResult,count);//pResult为指针,第二个参数使用引用传递,
	 //使用这个函数时,在函数内部分配的内存的指针并没有返回到主函数中
	  for ( int i = 0 ; i < count ; i++ )
	    printf("第 %d 个结果为 : %d\n",pResult[i]);
                               //执行了Compute1()函数后,pResult的值还是为NULL
      delete [] pResult;
	  pResult = NULL;
	 */

	//&pResult为指针的地址(即指针的指针),第二个参数使用引用传递
	Compute2(&pResult, count);
    for (int i = 0; i < count; i++)
		printf("第 %d 个结果为 : %d\n", i, pResult[i]);

	delete[] pResult;
	pResult = NULL;

	getchar();
	return 0;
}
  • 16
    点赞
  • 68
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天糊土

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值