一、回顧指針概念
早在本書第貳篇中我就對指針的實質進行了闡述。今天我們又要學習一個叫做“指向另一指針地址”的指針。讓我們先回顧一下指針的概念吧!當我們程序如下聲明變量:
? ?short int i;
? ?char a;
? ?short int * pi;
程序會在內存某地址空間上為各變量開辟空間,如下圖所示:

? ?i 變量在內存地址5的位置,占2個字節。
? ?a變量在內存地址7的位置,占1個字節。
? ?pi變量在內存地址9的位置,占2個字節。(注:pi 是指針,我這里指針的寬度只有2個字節,32位系統是4個字節)
接下來如下賦值:
? ?i = 50;
? ?pi = &i;
經過上在兩句的賦值,變量的內存映象如下:

? ?*pi=5; /* 就是等價于i = 5; */
你可以回看本書的第貳篇,那里有更加詳細的解說。
二、指針的地址與指向另一指針地址的指針
在上一節中,我們看到,指針變量本身與其它變量一樣也是在某個內存地址中的,如pi的內存起始地址是9。同樣的,我們也可能讓某個指針指向這個地址。看下面代碼:? ?short int **ppi; /* 這是一個指向指針的指針,注意有兩個“*”號 */
? ?*ppi = π
第一句:short int **ppi; —— 聲明了一個指針變量ppi,這個ppi是用來存儲(或稱指向)一個short int * 類型指針變量的地址。
第二句:&pi那就是取pi的地址,**ppi = &pi就是把pi的地址賦給了ppi。即將地址值9賦值給ppi。如下圖:

? ?ppi的值是多少呢?—— 9。
? ?*ppi的值是多少呢?—— 5,即pi的值。
? ?**ppi的值是多少呢?——50,即i的值,也是*pi的值。
呵呵!不用我說太多了,我相信你應明白這種指針了吧!
三、一個應用實例
(1)設計一個函數:void find1(char array[], char search, char *pa)要求:這個函數參數中的數組array是以0值為結束的字符串,要求在字符串array中查找字符是參數search里的字符。如果找到,函數通過第三個參數(pa)返回值為array字符串中第一個找到的字符的地址。如果沒找到,則為pa為0。
設計:依題意,實現代碼如下。
void find1(char array[], char search, char *pa)
{
? ?int i;
? ?for (i = 0; *(array + i) != 0; i++)
? ?{
? ? ? if ( *(array+i) == search)
? ? ? {
? ? ? ? ?pa = array + i;
? ? ? ? ?break;
? ? ? }
? ? ? else if (*(array+i) == 0)
? ? ? {
? ? ? ? ?pa = 0;
? ? ? ? ?break;
? ? ? }
? ?}
}
你覺得這個函數能實現所要求的功能嗎?
調試:我下面調用這個函數試試。
main()
{
? ?char str[] = {"afsdfsdfdf\0"}; /* 待查找的字符串 */
? ?char a = ’d’; /* 設置要查找的字符 */
? ?char *p = 0; /* 如果查找到后指針p將指向字符串中查找到的第1個字符的地址。 */
? ?find1(str, a, p); /* 調用函數以實現所要操作。 */
? ?if (0 == p)
? ?{
? ? ? printf("沒找到!\n"); /* 如果沒找到則輸出此句 */
? ?}
? ?else
? ?{
? ? ? printf("找到了,p = %d", p); /* 如果找到則輸出此句 */
? ?}
? ?return(0);
}
分析:上面代碼,你認為會是輸出什么呢?運行試試。
唉!怎么輸出的是:沒有找到!而不是“找到了,……”。
明明a值為’d’,而str字符串的第四個字符是’d’,應該找得到呀!
再看函數定義處:void find1(char array[], char search, char *pa)
看調用處:find1(str, a, p);
依我在第伍篇的分析方法,函數調用時會對每一個參數進行一個隱含的賦值操作。整個調用如下:
array = str;
search = a;
pa = p; /* 請注意:以上三句是調用時隱含的動作。*/
int i;
for(i =0; *(array+i) != 0; i++)
{
? ?if (*(array+i) == search)
? ?{
? ? ? pa = array + i;
? ? ? break;
? ?}
? ?else if (*(array+i)==0)
? ?{
? ? ? pa=0;
? ? ? break;
? ?}
}
哦!參數pa與參數search的傳遞并沒有什么不同,都是值傳遞嘛(小語:地址傳遞其實就是地址值傳遞嘛)!所以對形參變量pa值(當然值是一個地址值)的修改并不會改變實參變量p值,因此p的值并沒有改變(即p的指向并沒有被改變)。(如果還有疑問,再看一看《第五篇:函數參數的傳遞》了。)
修正:
void find2(char array[], char search, char **ppa)
{
? ?int i;
? ?for (i=0; *(array + i) != 0; i++)
? ?{
? ? ? if(*(array + i) == search)
? ? ? {
? ? ? ? ?*ppa = array + i;
? ? ? ? ?break;
? ? ? }
? ? ? else if(*(array + i) == 0)
? ? ? {
? ? ? ? ?*ppa = 0;
? ? ? ? ?break;
? ? ? }
? ?}
}
主函數的調用處改如下:
? ?find2(str, a, &p); /*調用函數以實現所要操作。*/
再分析:這樣調用函數時的整個操作變成如下:
array = str;
search = a;
ppa = &p; /* 請注意:以上三句是調用時隱含的動作。 */
int i;
for (i = 0; *(array + i) != 0; i++)
{
? ?if (*(array + i) == search)
? ?{
? ? ? *ppa = array + i
? ? ? break;
? ?}
? ?else if (*(array+i)==0)
? ?{
? ? ? *ppa=0;
? ? ? break;
? ?}
}
看明白了嗎?ppa指向指針p的地址。對*ppa的修改就是對p值的修改。你自行去調試。
經過修改后的程序就可以完成所要的功能了。看懂了這個例子,也就達到了本篇所要求的目的。