程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> 徹底搞定C語言指針 第六篇

徹底搞定C語言指針 第六篇

編輯:關於C語言

指向另一指針的指針

一、針概念:

早在本系列第二篇中我就對指針的實質進行了闡述 。今天我們又要學習一個叫做指向另一指針地址的指針。讓我們先回顧一下指針的概念吧!

當我 們程序如下申明變量:

short int i;

char a;

short int * pi;

程序會 在內存某地址空間上為各變量開辟空間,如下圖所示。

內存地址→6     7  8      9     10     11    12    13     14    15

------------------- ------------------------------------------------------------------

…  |      |  |  |  |  |  |  |  |  |

--------------------------------------- ----------------------------------------------

|short int i |char a|  |short int * pi|

圖中所示中可看出:

i 變量在內存地址5的位置,占兩個字節。

a變量在內存 地址7的位置,占一個字節。

pi變量在內存地址9的位置,占兩個字節。(注:pi 是指針,我這 裡指針的寬度只有兩個字節,32位系統是四個字節)

接下來如下賦值:

i=50;

pi=&i;

經過上在兩句的賦值,變量的內存映象如下:

內存地址→6      7  8     9     10     11    12    13  14     15

----- ---------------------------------------------------------------------------------

…  |    50  |  |  |    6   |  |  |  |

----------- ---------------------------------------------------------------------------

|short int i |char a|  |short int * pi|

看到沒有:短整型指針變量pi的值為6,它就是I變量的內 存起始地址。所以,這時當我們對*pi進行讀寫操作時,其實就是對i變量的讀寫操作。如:

*pi=5;   //就是等價於I=5;

你可以回看本系列的第二篇,那裡有更加詳細的解說。

二、指針的地址與指向另一指針地址的指針

在上一節中,我們看到,指針變量本身與其 它變量一樣也是在某個內存地址中的,如pi的內存起始地址是10.同樣的,我們也可能讓某個指針指向這 個地址。

看下面代碼:

short int * * ppi;    //這是一個指向指針的指針,注意 有兩個*號

ppi=π

第一句:short int * * ppi;——申明了一個指針變量 ppi,這個ppi是用來存儲(或稱指向)一個short int * 類型指針變量的地址。

第二句: &pi那就是取pi的地址,ppi=π就是把pi的地址賦給了ppi.即將地址值10賦值給ppi.如下圖:

內存地址→6     7  8     9     10     11    12    13   14    15

------------------------------------------------------------------------ ------------

…  |    50     |  |  |  6  |  10  |   |

---------------------------------------------------------------------------------- --

|short int i|char a|  |short int * pi|short int ** ppi|

從圖中看出,指針變 量ppi的內容就是指針變量pi的起始地址。於是……

ppi的值是多少呢? ——10.

*ppi的值是多少呢?——6,即pi的值。

**ppi的值是多少 呢?——50,即I的值,也是*pi的值。

呵呵!不用我說太多了,我相信你應明白這種 指針了吧!

三、一個應用實例

1. 設計一個函數:void find1(char array[], char search, char * pi)

要求:這個函數參數中的數組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;
}
}
}

你覺得這個函數能實現所要求的功能嗎?

調試:

我下面調用這個函數 試試。

void main()
{
char str[]={“afsdfsdfdf\0”};  //待 查找的字符串
char a=’d’;   //設置要查找的字符
char * p=0;  //如果 查找到後指針p將指向字符串中查找到的第一個字符的地址。
find1(str,a,p);  //調用函數以實 現所要操作。
if (0==p )
{
printf (“沒找到!\n”);//1.如果沒找到則 輸出此句
}
else
{
printf(“找到了,p=%d”,p);  //如果找到則 輸出此句
}
}

分析:

上面代碼,你認為會是輸出什麼呢?

運 行試試。

唉!怎麼輸出的是:沒有找到!

而不是:找到了,……。

明明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值的修改。

你自行去調試。

經過修改後的程序就可以完 成所要的功能了。

看懂了這個例子,也就達到了本篇所要求的目的。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved