數(shù)組與指針_第1頁
已閱讀1頁,還剩34頁未讀, 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

1、,,數(shù)組與指針,1.空間分類2.為什么用指針3.指針的定義及使用方式4.指針的訪問方式(即變量操作的本質)5.數(shù)組同指針的關系6.數(shù)組和指針作為函數(shù)的參數(shù)和返回值,棧空間堆空間,空間分類,數(shù)組-物理空間存放的本質,定義數(shù)組就是申請了一塊連續(xù)的內存空間。用戶可操作的空間大小等于數(shù)組元素*每個元素所占的空間大小。數(shù)組元素連續(xù)存放在這塊空間中。如: int intarray[5];占用了20個字節(jié),因為每個整型數(shù)占四個字節(jié)。

2、如給intarray[3]賦值為3,如果這塊空間的起始地址為100,那么在內存中的情況是:當你引用變量intarray[idx]時,系統(tǒng)計算它的地址100+idx*4,對該地址的內容進行操作。,參照幾何坐標系,數(shù)組下標超界問題,C/C++語言不檢查數(shù)組下標的超界。如定義數(shù)組 int intarray[10]; 合法的下標范圍是0 – 9,但如果你引用intarray[10],系統(tǒng)不會報錯。如數(shù)組intarray 的起始地址是100

3、0,當引用intarray[10]時,系統(tǒng)對1040號內存進行操作。而1040可能是另一個變量的地址解決方法(1) 由程序員自己控制。在對下標變量進行操作前,先檢查下標的合法性。 (2) 利用容器等,數(shù)組的缺點,必須知道數(shù)組的確定類型和空間大小,才能定義數(shù)組。數(shù)組的大小受到棧大小的限制。通常棧的大小是2M。,指針的概念,如在某一程序中定義了 int x = 2;如系統(tǒng)給x分配的空間是1

4、000號單元,則指向x的指針是另一個變量p,p中存放的數(shù)據(jù)為10001000號單元的內容有兩種訪問方式:訪問變量x (直接訪問)訪問變量p指向的單元的內容(間接訪問),定義指針變量,定義指針變量要告訴編譯器該變量中存放的是一個地址。指針變量的主要用途是提供間接訪問,因此也需要知道指針指向的單元的數(shù)據(jù)類型指針變量的定義 類型標識符 *指針變量; 如:int *intp; double *doublep;

5、 int *p, x, *q;,類型標識符的作用??,指針變量的操作,如何讓指針指向某一變量?因為我們不知道系統(tǒng)分配給變量的真正地址是什么。用取地址運算符 “&” 解決。如表達式 “&x” 返回的是變量 x 的地址。如:intp = &x;& 運算符后面不能跟常量或表達式。如 &2 是沒有意義的,&(m * n + p )。也是沒有意義的如何通過指針變量處理和改變它所指向

6、的單元的值?用地址解析運算符 “*” 解決。如 *intp 表示的是 intp 指向的這個單元的內容。如:*intp = 5 等價于 x = 5在對 intp 使用引用運算之前,必須先對 intp 賦值,指針實例,如有:int X, *intp, Y;X=3;Y=4;intp=&X;,如執(zhí)行:*intp=Y+4;,注意:不能用 intp=100;因為我們永遠不知道變量存儲的真實地址,而且程序每次運行變量地址

7、可能都不同。,指針使用,指針變量可以指向不同的變量。如上例中intp指向x,我們可以通過對intp的重新賦值改變指針的指向。如果想讓intp指向y,只要執(zhí)行intp=&y就可以了。這時,intp與x無任何關系。同類的指針變量之間可相互賦值,表示二個指針指向同一內存空間??罩羔樦羔槢]有指向任何空間空指針用常量NULL表示,NULL的值一般賦為0不能引用空指針指向的值野指針(沒有初始化的指針),指針變量的使用,設有定義

8、 int x, y; int *p1,*p2;,執(zhí)行語句:x=23;y=234;,執(zhí)行語句:p1=&x;p2=&y;,執(zhí)行語句:*p1=34;p2=p1;,指針實例,有以下結構,比較執(zhí)行 p1=p2和 *p1= *p2后的不同結果。,指針的初始化,指針在使用前必須初始化。和別的變量一樣,定義指針不初始化是一個比較普通的錯誤。沒有初始化的指針可能指向任意地址,對這些指針作操作可能會導致程序

9、錯誤(野指針)。NULL是一個特殊指針值,稱為空指針。它的值為0。它可被用來初始化一個指針,表示不指向任何地址。,思考:int *p; *p = 5; 有什么問題?,指針與數(shù)組,在C++中,指針和數(shù)組關系密切,幾乎可以互換使用數(shù)組名可以看成是常量指針,對一維數(shù)組來說,數(shù)組名是數(shù)組的起始地址,也就是第一個元素的地址如執(zhí)行了p=array,則p與array是等價的,對該指針可以進行任何有關數(shù)組下標的操作,數(shù)組實際訪問方式: C+

10、+語言的下標運算符[ ]是以指針作為操作數(shù)的,fibon[i]被編譯系統(tǒng)解釋為*(fibon+i)即表示為fibon所指(固定不可變)元素向后第i個元素。無論以下標方式或指針方式存取數(shù)組元素時,系統(tǒng)都是轉換為指針方法實現(xiàn)。,通過指針訪問數(shù)組時,下標有效范圍由程序員自己檢查。,數(shù)組元素的指針表示,方法3: for ( p=a; p<a+10; ++p ) cout << *p ;,方法2:

11、 for ( i=0; i<10; ++i ) cout << *(a+i);,方法1: for ( i=0; i<10; ++i ) cout << a[i];,方法4: for ( p=a, i=0; i<10; ++i ) cout << *(p+i);,方法5: for (

12、 p=a, i=0; i<10; ++i ) cout << p[i] ;,下列程序段 有無問題? for ( i=0; i<10; ++i ) { cout << *a ; ++a; },,指針同樣可以進行”++”,”--“運算,運算結果也是指向后一個或前一個數(shù)組元素。,*但是有”++”和”--”的表達式往往容易出錯

13、,必須小心使用,如:y=*pfib++;由于后”++”的優(yōu)先級高于”*”,所以該表達式等效于y=*(pfib++),又因是后”++”,所以y中取值為*pfib,而pfib增1后指向下一個元素。這條語句在C++中是常用的。千萬不可誤解為將pfib所指目標增1。,動態(tài)內存分配,什么時候需要動態(tài)分配內存?實例:順序對一批文件進行解析,但是不知道文件的大小,如何建立緩沖區(qū)?參看一個人臉檢測的Ground Truth文件格式,C語言方

14、法malloc函數(shù)原型:void * malloc(size_t n);n是要分配的內存的大小(字節(jié)為單位),返回值是分配內存的塊的首地址,關鍵代碼:int * array;array = (int *)malloc(10 * sizeof(int));注意:單位,內存大小不能寫成數(shù)組元素的個數(shù),需要注意的問題(1)malloc函數(shù)是一個庫函數(shù),它并不是C語言中的關鍵字:需要頭文件才可以使用該函數(shù)并不是所有的

15、平臺都可以使用該函數(shù),尤其是一些單片機系統(tǒng),free函數(shù)原型:void free(void * p);p是要釋放的已分配內存的塊的首地址,釋放一塊動態(tài)分配的內存:例如:int *p;p = (int *)malloc(sizeof(int));free(p);,動態(tài)內存申請與釋放,C++中由new 和 delete兩個運算符替代- 運算符new用于進行內存申請: 申請動態(tài)變量:p = new type; 申

16、請動態(tài)數(shù)組:p = new type[size]; 申請動態(tài)變量并初始化:p = new type(初值) - 運算符delete 釋放 new分配的內存: 釋放動態(tài)變量:delete p; 釋放動態(tài)數(shù)組:delete [] p;,//為簡單變量動態(tài)分配內存,并作初始化int main(){ int *p; p = new int(99); //動態(tài)分配內存,并將99作為初始化值賦給它 c

17、out<< *p; delete p; return 0;},動態(tài)內存申請與釋放,//動態(tài)字符串的使用int main(){int *p; char *q; p = new int(5); q = new char[10]; strcpy(q, "abcde"); cout << *p << endl; cout << q <<

18、endl; delete p; delete [ ]q; return 0;},輸出結果:5abcde,動態(tài)分配的檢查,new操作的結果是記錄申請到的空間的起始地址及大小(隱式)當系統(tǒng)空間用完時,new操作可能失敗new操作失敗時,返回空指針/NULL,動態(tài)內存申請與釋放,//動態(tài)分配檢查int main(){ int *p; p = new int; if( p== NULL ) //if (

19、 NULL == p ) { cout << "allocation failure\n"; return 1; } *p = 20; cout << *p; delete p; return 0;},assert宏,assert()宏在標準頭文件cassert中 assert()有一個參數(shù),表示斷言為真的表達式,預處理器產生測試

20、該斷言的代碼。如果斷言不是真,則在發(fā)出一個錯誤消息后程序會終止。,#include #include //包含assert宏的頭文件int main(){ int *p; p = new int; assert ( p != 0 ); //p等于0,則退出程序 *p=20; cout << *p; delete p; return 0;},內存分配的進一步介紹,靜態(tài)分配:對全局

21、變量和靜態(tài)變量,編譯器為它們分配空間,這些空間在整個程序運行期間都存在自動分配:函數(shù)內的局部變量空間是分配在系統(tǒng)的棧工作區(qū)。當函數(shù)被調用時,空間被分配;當函數(shù)執(zhí)行結束后,空間被釋放動態(tài)分配:在程序執(zhí)行過程中需要新的存儲空間時,可用動態(tài)分配的方法向系統(tǒng)申請新的空間,當不再使用時用顯式的方法還給系統(tǒng)。這部分空間是從被稱為堆的內存區(qū)域分配。,內存泄漏,動態(tài)變量是通過指針間接訪問的。如果該指針被修改,這個區(qū)域就被丟失了。堆管理器認為你在繼續(xù)

22、使用它們,但你不知道它們在哪里,這稱為內存泄露。為了避免出現(xiàn)孤立的區(qū)域,應該明白地告訴堆管理器這些區(qū)域不再使用。可以采用delete操作,它釋放由new申請的內存。當釋放了內存區(qū)域,堆管理器重新收回這些區(qū)域,而指針仍然指向堆區(qū)域,但不能再使用指針指向的這些區(qū)域。要確保在程序中同一個區(qū)域釋放一次。釋放內存對一些程序不重要,但對有些程序很重要。如果你的程序要運行很長時間,而且存在內存泄漏,這樣程序會耗盡所有內存,直至崩潰。,動態(tài)空間

23、分配示例,輸入一批數(shù)據(jù),計算它們的和。數(shù)據(jù)個數(shù)在設計程序時尚無法確定。存儲一批數(shù)據(jù)應該用數(shù)組,但C++語言的數(shù)組大小必須是固定的。該問題有兩個解決方案:開設一個足夠大的數(shù)組,每次運行時只使用一部分。缺點:浪費空間用動態(tài)內存分配根據(jù)輸入的數(shù)據(jù)量申請一個動態(tài)數(shù)組,#include int main(){ int *p, i, n, sum=0; cout > n; p = new int[n]; if

24、 ( p == NULL ) return 1; for ( i=0; i> p[i]; for( i=0; i<n; ++I ) sum += p[i]; cout << "Number of elements:" << n << endl; cout << "Sum of the elements:" &l

溫馨提示

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

評論

0/150

提交評論