輕松學C之指針與引用_第1頁
輕松學C之指針與引用_第2頁
輕松學C之指針與引用_第3頁
輕松學C之指針與引用_第4頁
輕松學C之指針與引用_第5頁
已閱讀5頁,還剩107頁未讀 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1、第7章 指針與引用指針和引用被認為是C+中的特殊數據類型,它與前面章節介紹的基本數據類型不同。使用指針和引用可使程序簡潔、緊湊和高效,所以對于每一個學習C+語言的人,都要掌握指針和引用的使用方法。指針和引用的用法比較特殊,而且運用非常靈活。本章將詳細講述指針和引用的概念和使用。7.1 指針概述計算機的數據都是存儲在內存中,內存是按字節排列的存儲空間,每個字節都有一個編號,被稱為地址,程序中用到的數據和聲明的變量都存放在這一個個字節中,不同類型的數據和變量占用的字節字數不同,習慣上將某個變量占用的字節數稱為內存單元,指針就是記錄這些地址的變量,而指針的類型表示指針指向地址存儲的數據類型。準確地理

2、解指針的概念是掌握指針的前提。 7.1.1 指針的基本概念簡單地說,指針是一個地址,它指向存儲某一個數據的存儲地址。此外,還有一個指針變量的概念如圖7-1所示。圖7-1 指針變量及其訪問方法在現實生活中,指針的概念也是比較常見的。例如,高速公路上的交通指示牌指示了某地的地理位置,這就是指針,而這個指示牌就是指針變量,用于存儲指針,如圖7-2所示。圖7-2 指針的概念在C+中,如果在內存中存儲了一個變量a,其值為100,那么用通過指針變量p訪問該變量的流程如圖7-3所示。圖7-3 指針可以看到,指針變量p指向變量a。在理解“指向”的時候,應該了解指針變量p中存有變量a的地址,通過該地址就能找到變

3、量a。因此,在C+語言中用指針來表示指向關系,即指針就是地址。注意:在C+具體程序中參加數據處理的量不是指針本身的量,而是指針所指向的變量,即指針所指向的內存區域中的數據(稱為指針的目標)才是需要處理的數據。7.1.2 定義指針變量指針是一種復合型的數據類型,基于該類型聲明的變量稱為指針變量,該變量存放在內存中的某個地址,與其他基本數據類型一樣,使用指針之前也必須先定義指針變量。在C+中,定義指針變量的一般形式如圖7-4所示。圖7-4 定義指針變量的一般形式需要注意的是,定義一個指針變量必須用符號“*”,它表明其后的變量是指針變量,但不要認為“*p”是指針變量,指針變量是p而不是*p。此外,有

4、相同存儲類型和數據類型的指針可以在一行中說明,也可以和同類型的普通變量在一起說明,如圖7-5所示。圖7-5 指針變量的說明當在一行中定義多個同一類型的指針時,用逗號隔開各指針變量標識符,并且每個變量前都要加上“*”。否則該變量就不是一個指針,而是一個普通類型的變量。如圖7-6中定義的變量語句。圖7-6 不加“*”含義不同注意:定義指針變量時,“*”可以出現在類型名和變量名之間的任何位置,如下int *p,q;等價于:int* p,q;p是整型指針變量,q是整型變量。第二種寫法容易理解為p,q都是指針變量。故建議寫成第一種形式。指針變量存儲的內容是內存中某個字節的地址,指針變量占用的內存字節數隨

5、系統的不通而不同。7.1.3 初始化指針定義了一個指針后,在使用此指針前,必須給它賦一個合法的值。在C+中,可以在定義指針的同時通過初始化來給指針賦值,也可以在使用之前給指針賦值。一般來說,C+在定義指針的同時初始化指針的形式如圖7-7所示。圖7-7 C+在定義指針的同時初始化指針的形式注意:當把一個變量的內存地址作為初始值賦給指針時,該變量必須在指針初始化之前已做說明,因為變量只有在說明之后才被分配一定的內存地址。此外,該變量的數據類型必須與指針的數據類型一致,因此不能將一個浮點型變量的地址賦值給整型的指針變量。同時,也可以向一個指針賦初值作為另一個指針變量,即把另一個已經初始化的指針賦給一

6、個指針。此時,這兩個指針指向同一變量的內存地址,如圖7-8所示。圖7-8 兩個指針指向同一變量的內存地址指針的初始化在具體程序中非常重要,一旦指針的初始化出現問題,就可能導致程序崩潰。【示例7-1】下面程序定義了整型指針變量p1和p2,并為其賦初值,其實現代碼及結果如圖7-9所示。圖7-9 指針的初始化實例注意:在給指針變量初始化時,不能為其賦一個常量,否則程序將通不過編譯。此外,上述程序中使用*p1和*p2取出其中存儲的變量a的值,這是下面將要介紹的指針的訪問問題。7.2 指針的訪問如果定義一個指針,并使其值為某個變量的地址,則可以通過這個指針間接地訪問在這個地址中存儲的值。如示例7-1中,

7、通過*符號取出存儲在該地址中的值。事實上,在C+中有兩個有關指針訪問的運算符,下面將依次進行說明。7.2.1 指針的值指針的值是一個地址。在C+中,為了取得一個變量的地址,引入了取地址運算符“&”來取得一個變量的地址,其語法如圖7-10所示。圖7-10 取地址運算符&注意:取地址運算符&只能應用于內存中存在的數據,如變量、數組元素等,不能用于表達式、常數或寄存器變量。【示例7-2】下面示例定義了兩個指針變量p1和p2,其都指向整型變量a后將值分別輸出,其實現代碼及結果如圖7-11所示。圖7-11 指針的值實例上述代碼在指針的定義中,指針變量是p1和p2而不是*p1和*p2,因此要對一個指針賦值

8、,等號左邊不應該加*號。注意:C+中不允許把一個無效的地址,比如數字賦給指針。指針變量和一般的變量是類似的,存放的值是可以改變的。7.2.2 訪問指針數據通過&運算符可以獲取變量的地址,可將其賦值給指針,即完成了將指針指向該變量的操作。而C+可以通過“*”運算符將指針指向的變量值取出,進行各種運算。在C+中,*運算符為取值運算符,也稱為指針運算符、指向運算符或間接運算符,*p代表p所指向的變量。【示例7-3】下面程序接收用戶從鍵盤輸入的兩個整數,并通過*運算符將指針變量p1和p2的值取出并輸出,其實現代碼及結果如圖7-12所示。圖7-12 訪問指針數據實例通過指針來訪問變量是一種間接的方式,其

9、速度略慢于直接訪問。但給程序的開發帶來了很大的靈活性,其原因在于指針也是一個變量,可以在運行時修改其指向,從而達到“使用一個指針,訪問多個變量”的目的。7.2.3 小結指針p由于引進了指針的概念,在程序中要注意區分下面三種表示方法所具有的不同意義。例如,有一個指針p,其不同格式代表的意義不同如圖7-13所示。圖7-13 指針p不同格式代表的意義【示例7-4】下面程序接收用戶輸入的兩個整數后,分別輸出p、*p和&p的值,實現代碼及結果如圖7-14所示。7.3 指針的算術運算指針變量也有加減運算,它可以與某個整型數相加減,也可以與指針相減。但指針與指針相加或相乘除都是沒有意義的。指針的值是一個內存

10、地址,而一個內存地址可以用一個整型數表示。因此,指針的算術運算可以看做是整型數間的一個運算。7.3.1 指針與整數的加減運算指針與整數的加減運算是指將指針作為地址量加上或減去一個整數n,其意義及效果如圖7-15所示。圖7-15 指針與整數的加減運算由于指針可以指向不同數據類型,即數據長度不同的數據,所以這種運算的結果取決于指針指向的數據類型。例如一個int型(4字節大小)指針加減整型數的運算如圖7-16所示。圖7-16 int型指針加減整數的運算因此,對于某種數據類型的指針p來說,其實際操作如圖7-17所示。圖7-17 某種數據類型的指針p的實際操作7.3.2 指針加減1運算指針與1的加減運算

11、是一種特殊的指針與整數的加減運算。由于指針的加減1運算在具體程序中使用廣泛,并有自己的表示方法,因此本小結將單獨講解。同樣地,指針加減1單項運算也是地址計算,它具有指針與整數的加減運算特點,指針的加1、減1單項運算是指針中的地址值的變化。在C+中,指針p的加1、減1運算表示如圖7-18所示。圖7-18 指針p的加1、減1運算表示運算后指針地址值的變化量取決于它指向的數據類型。例如,一個int型指針p存放的地址為1000,當執行p+、p后其地址變化如圖7-19所示。圖7-19 執行p+、p后其地址變化指針加1、減1單項運算與前面所講的自增自減運算符類似,也分為前置運算和后置運算,如圖7-20所示

12、。圖7-20 指針加1、減1單項運算分類當指針加1、減1運算和其他運算出現在一個表達式中時,要注意它們之間的結合規則和運算順序。例如,表達式y=*p+的分析過程和運算順序如圖7-21所示。圖7-21 表達式y=*p+的分析過程和運算順序7.3.3 指針的相減運算指針的相減運算是指兩個指針所指向的變量類型相同時可以進行減法運算。其運算結果是兩個地址之間可存放的變量個數,而不是地址量。例如,兩個int型指針px和py進行相減運算如圖7-22所示。圖7-22 指針的相減運算注意:指針變量也可以進行關系運算,用于比較兩個指針是否相等。指針也可以賦值給相同類型的指針變量。7.4 特殊指針前面章節學習了數

13、組和函數,C+允許指針指向數組和函數。本節將見紹幾種特殊的指針。7.4.1 數組指針在C+中,數組指針是一個指向數組的指針,其定義的一般形式如圖7-23所示。圖7-23 數組指針【示例7-7】下列程序定義了一個數組指針,并通過該指針指向某一整型數組,輸出其中所有數組元素,其實現代碼及結果如圖7-24所示。圖7-24 數組指針實例7.4.2 指向函數的指針函數指針在C+中,函數指針是一個指向函數的指針,即指針存儲的是函數的首地址。其定義的一般形式如圖7-25所示。圖7-25 函數指針在定義了指向函數的指針變量后,在使用此函數指針之前,必須先給它賦值,使它指向一個函數的入口地址。由于函數名是函數在

14、內存中的首地址,因此可以將函數名賦給函數指針變量,賦值的一般語法格式如圖7-26所示。圖7-26 函數指針賦值【示例7-8】下面程序定義一個函數指針p,該指針指向實現兩個整型值交換的swap()函數。在使用該函數指針p前為其賦值,并在main()函數中調用了該函數指針,實現代碼及結果如圖7-27所示。圖7-27 函數指針實例7.4.3 指針數組指針數組就是其元素為指針的數組,如圖7-28所示。圖7-28 指針數組指針數組是指針的集合,其每一個元素都是指針變量,并且它們具有相同的存儲類型和指向相同的數據類型。指針數組在使用前必須先聲明,一般地說,C+中聲明指針數組的一般形式如圖7-29所示。圖7

15、-29 指針數組的聲明與普通指針類似,指針數組在使用前也必須先賦值,否則指針可能指向沒有意義的值。指針數組賦初值與一般數組的賦值類似,可以在聲明指針數組的同時進行初始化。【示例7-9】下面程序定義了一個指向字符串的包含5個元素的指針數組,初始化后將其倒序輸出,其實現代碼及結果如圖7-30所示。圖7-30 指針數組實例說明:要嚴格區分數組指針和指針數組噢!7.4.4 二級指針指針的指針雖然指針存儲的是一個地址,但指針本身也是一個變量,在內存中占據一定的空間,并且具有一個地址,這個地址也可以利用指針來保存。因此,同樣可以聲明一個指針來指向它,這個指針稱為指向指針的指針。在C+中,指向指針的指針也被

16、稱為二級指針,在聲明指向指針的指針時,其形式與聲明指針類似,但需加上兩個間接取值的運算符“*”,聲明形式如圖7-31所示。圖7-31 二級指針的聲明與定義【示例7-10】下面程序聲明了一個指針p,一個指向指針的指針pp,將指針pp指向指針p,實現代碼及輸出結果如圖7-32所示。圖7-32 二級指針實例7.4.5 多級指針二級以上的指針多級指針是指含有多個間接取值運算符“*”的指針,其聲明形式與二級指針類似,如圖7-33所示。圖7-33 多級指針的聲明在C+中常用的是二級指針,多級指針只需了解就可以啦!在這不做詳細講解。7.5 指針的應用C+中,使用指針可使程序簡單、可讀性強,并且指針的使用非常

17、靈活。本節將重點講解指針在數組、字符串、函數中的應用及動態內存分配。7.5.1 指向一維數組的指針任何數據類型中的數組元素,除了用數組名加下標的方法進行訪問外,還可以用指針訪問。用指針訪問數組形式簡單、使用靈活,程序的可讀性強。1指針訪問數組元素用指針指向數組就是讓指針指向這段連續內存的首地址,即數組中第一個元素(下標為0)的地址。定義一個指向數組的指針變量,只要其與數組元素類型相同即可。由于數組是一段連續的內存,指針可以指向數組,而且可以通過加、減整數來移動指針。所以,可以通過指針來訪問數組,即數組中的元素。使用指針訪問數組,同用下標訪問數組的效果是一樣的。例如一個指向數組arr首地址的指針

18、p,訪問第i+1個元素(下標為i),可以用*(p+i),也可以用arri,這兩種方法是等價的。由于數組名代表的是數組的首地址,所以也可以用*(arr +i)來訪問第i+1個元素,如圖7-34所示。圖7-34 指針訪問數組元素【示例7-11】下面程序通過幾種方式對數組元素進行訪問,實現代碼及結果如圖7-35所示。圖7-35 幾種方式對數組元素進行訪問無論是采用下標、地址還是指針都可以得到相同的訪問結果。但是,在數組元素的訪問中,使用指針進行訪問更為靈活。2指向一維數組在實際程序中一維數組的使用最為頻繁,因此使用指針指向一維數組是具體應用中使用最多的。【示例7-12】下面程序將一個數組的元素進行反

19、轉,即第一個元素放到最后一個,第二個元素放到倒數第二個,依此類推,其實現代碼及結果如圖7-36所示。圖7-36 指向一維數組的實例注意:在使用指針訪問數組時不要越界,即保證指針指向數組第一個到最后一個元素。7.5.2 指向二維數組的指針多維數組尤其是二維數組在具體程序中的應用非常廣泛,通過指針來訪問二維數組元素也是常用的。對于一維數組array10而言,指針指向為數組的首地址,即&array0的值。而對于二維數組array1010而言,數組的首地址為&array00的值。因此,對于二維數組中的元素arrayij有多種訪問方法如圖7-37所示。圖7-37 二維數組中的元素arrayij的訪問方法

20、例如,一個數組a35中元素a23的三種等價訪問方法如圖7-38所示。圖7-38 元素a23的三種等價訪問方法在二維數組a35中,其是一個3*5的矩陣,包括三行,每一行都有起始地址。C+中以a0、a1、a2分別表示第0行、第1行、第2行的起始地址,即該行第0列元素的地址。注意:二維數組的a0、a 1、a2并不是一個元素,而是一行首地址,正如同一維數組名是數組起始地址一樣。因此,a0的值等于&a00,a1的值等于&a10,a2的值等于&a20。【示例7-13】下面程序指向二維數組array首元素的指針p,通過幾種指針訪問元素的方式將數組中的元素依次輸出,其實現代碼及結果如圖7-39所示。圖7-39

21、 指向二維數組指針實例7.5.3 指向字符串的指針在C+中,字符串是用字符數組表示和存儲的。數組的訪問能夠通過指針來實現,因此字符串也同樣可以通過指針來訪問。指向字符串的指針就是一個char類型的指針。與普通指針一樣,字符串指針在使用前也必須先定義。例如,下面語句定義了一個字符串str,并定義了一個指向該字符串的指針p,并為該指針進行初始化。如圖7-40所示。圖7-40 指向字符串的指針【示例7-14】下面示例用字符串指針訪問字符串,并使用字符串函數對字符串進行比較和計算長度操作,實現代碼及結果如圖7-41所示。圖7-41 指向字符串指針實例7.5.4 指針作為函數參數在函數的參數列表中,可以

22、使用指針類型的參數。傳遞給指針參數的實參可以是一個指針變量,也可以是一個變量的地址。在C+中,使用指針作為參數可以提高傳遞參數的效率,而且在函數中可以修改實參指針所指變量的值。例如,下面聲明函數function()時其形式參數就是一個int類型的指針,在調用函數function()時必須傳入一個int型的指針變量,如圖7-42所示。圖7-42 指針作為函數參數注意:使用指針作為函數的形式參數,在調用該參數時傳遞的是地址。【示例7-15】下面程序將指針作為函數的參數進行傳遞,完成兩個數之間的互相交換功能,使用的是地址傳遞的方式,其實現代碼及結果如圖7-43所示。圖7-43 指針作為函數參數實例代

23、碼“change(&x,&y);”中的change()函數成功地實現了x和y之間的數據交換,函數的形參是兩個int型指針,將調用函數中的變量地址作為實參,賦值給形參,完成對調用函數中變量的處理。7.5.5 指針作為函數的返回值指針函數指針函數是指函數的返回值為指針類型。指針函數在調用后返回一個指針,通過指針中存儲的地址值,主調函數就能訪問該地址中存放的數據,并通過指針算術運算訪問這個地址的前、后內存中的值。指針函數與一般函數的區別如圖7-44所示。圖7-44 指針函數與一般函數的區別在C+中,指針函數與一般函數的聲明和定義形式類似,不同點在于其返回值必須為指針,其一般語法形式如圖7-45所示。

24、圖7-45 指針函數的聲明在具體程序中,指針函數的優勢在于其能夠返回一組數據,因此指針函數多用于數組和字符串的處理。【示例7-16】下面程序定義了一個包含5個字符串的指針數組,將這些字符串進行比較后輸出其中最大的一個,其實現代碼及結果如圖7-46所示。圖7-46 指針函數實例注意:函數指針與指針函數不要混淆噢!7.5.6 動態內存分配指針存儲的是內存地址,在使用指針的時候,需要保證指向地址的有效性。C+程序中的內存分配分為兩種,如圖7-47所示。圖7-47 C+程序中的內存分配在C+中,通過關鍵字new和delete來實現程序的動態內存分配和回收,如圖7-48所示。圖7-48 動態內存分配和回

25、收其中,關鍵字new實現內存分配,如果需要對分配出的內存進行初始化,則在類型后面加上一個括號,并帶有初始值。因此,C+中動態分配內存的一般形式如圖7-49所示。圖7-49 C+中動態分配內存的一般形式此外,通過關鍵字new分配的內存必須由開發者自己去釋放。一塊內存如果沒有被釋放,則可以一直存在到該應用程序結束。在C+中,使用delete來釋放內存,其一般形式如圖7-50所示。圖7-50 delete釋放內存的一般形式【示例7-17】下面程序為一個整數和一個整型數組動態分配內存空間,使用該空間存儲用戶輸入的數組元素,最后將這些空間釋放,實現代碼及結果如圖7-51所示。圖7-51 動態內存分配實例

26、用new申請動態數組,格式如下:類型名 *指針變量名= new 類型名元素個數;其中,元素個數可以是變量。7.6 引用雖然指針的使用非常靈活和高效,但使用起來卻不是非常方便。如果使用不當,很容易導致某些不易察覺的錯誤。為此,C+引入了引用。7.6.1 引用的應用在C+中,引用也是一種數據類型。引用不能獨立存在,而只能依附于一個變量。所以定義一個引用必須指明是哪個變量的引用。定義一個引用包括目標變量的數據類型、引用修飾符“&”、引用的標識符及目標變量的標識符。其語法如圖7-52所示。圖7-52 引用的一般語法形式注意:此處的“&”不是取地址運算符,而是一個引用修飾符。引用一旦定義,則始終跟其目標變量綁定,而不能改變為其他變量的引用。假如b是變量a的引用,則在b的生命周期內,b始終都是a的引用,而不能再改變為其他變量的引用。此外,對于引用在其生命周期內完全可以替代其目標變量。也就是說,所有施加于引用上的操作,其效果等同于直接對引用的目標變量操作。而且一旦目標變量的值發生了改變,引用的值也會發生同樣的改變。如圖7-53所示的程序體現了引用的這個特征。圖7-53 引用的特征鑒于引用的不可變更性,以及引用與目標變量的等價性,一個變量的引用也可以看做是該變量的別名。定義一個引用只不過是給變量另外命名。這樣兩個名字擁有一個實體,對一個名字的

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論