1. 程式人生 > >“指向指標的指標”的作用和應用

“指向指標的指標”的作用和應用

(1)在子函式中修改主函式傳過來的指標的指向

  • 比如主函式申明一個指標變數,且不為其分配指向空間(只是指向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;
				  */

	Compute2(&pResult, count); //&pResult為指標的地址(即指標的指標),第二個引數使用引用傳遞
	for (int i = 0; i < count; i++)
		printf("第 %d 個結果為 : %d\n", i, pResult[i]);

	delete[] pResult;
	pResult = NULL;

	getchar();
	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)用指標的指標指向指標陣列

#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] = { "hello", "zhuyu", "jiajia", "linux","Ubuntu" };//如果想使用 需使用指標陣列即*a[5] 宣告一個有五個字串指標的陣列。
	                                                              //但是由於每個元素都是指標字串,所以只能夠讀取,而不能夠寫入。
	change(a);
	return 0;
}