




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
1、第 8 章善于利用指針一、指針在程序中的用途二、地址和指針的概念三、變量的指針和指針變量四、數組與指針五、字符串與指針六、返回指針值的函數主要內容:一、指針在程序中的用途有效的表示復雜的數據結構能動態分配內存方便的使用字符串直接處理內存地址 總之,指針的應用,使程序簡潔、緊湊、高效。二、指針的概念1.數據在內存中的存儲、讀取過程 例如:整型變量 i , j , k ; 在編譯時為變量分配內存,內存示意圖如圖 1 所示.(2) 給變量賦值為 i=3; j=6; k=9;(1) 假設變量 i,j,k 被分配的 內存地址分別為2000,2002,2004(3) 通常,在程序中通過變量名對變量 進行存
2、取。200020022004變量i變量j變量k內存中用戶數據區。36920003010內存地址編號變量 p其實程序經過編譯后已將變量名轉換為變量的地址,對變量值的存取都是通過變量的地址進行的。圖1(1) 直接訪問方式 按變量地址存取變量值的方式。 如果讀取變量 i的值,直接到為變量i分配的存儲單元(2000、2001字節)中取出i的值(3)即可。(2) 間接訪問方式 先將變量 i 的地址存放在另一個變量p中,如果讀取變量 i的值,先找到變量p,從p中取出內容(2000,即變量i的起始地址),然后到2000、2001字節中取出i的值(3)。 即通過變量p訪問為變量i分配的內存單元。訪問變量的兩種
3、方式:直接訪問示意圖間接訪問示意圖 表示將數值3送到變量i中,可有兩種表達方法:(1)將3送到變量i所標志的單元中。即直接訪問方式(2)將3送到變量p所指向的單元(變量i)中。 即間接訪問方式i32000i320002000p注意:我們并不關心變量p的存儲地址,對 變量p的訪問屬于直接訪問。三、 指針變量1.變量的指針 變量的地址稱為變量的指針。2. 指針變量 存儲變量地址的變量稱為指針變量,用來指向另一個變量。3. * 操作符 為了表示指針變量與它所指向的變量的之間的關系,在程序中用 * 符號表示“指向”。例如,P代表指針變量,* P則表示P所指向的變量。3i20002000P*P以下兩個語
4、句作用相同: i=3; *P=3; 三、 指針變量(續)4.指針變量的定義 int i , j ; int *pointer1, *pointer2;定義形式: 基類型 *指針變量名; 舉例 說明 (1)指針變量名前的*,表示該變量是指針型的變量。指針變量名為pointer1,而非 *pointer1。(2)定義指針變量時必須指明基類型。*注:以后幾張幻燈片中提到的pointer1 pointer2是基于此例的。如何使一個指針變量指向一個變量呢? 使用取地址運算符 & ,即 :pointer1=&i; pointer2=&j;賦值語句pointer1=&i;實現將變量i的地址保存入指針變量po
5、inter1中。如右圖所示。3ipointer1*pointer1你能畫出第二個賦值語句的示意圖嗎? 三、 指針變量5.指針運算符 & 三、 指針變量(續)6.指針變量的引用 與指針變量有關的兩個運算符: & : 取地址運算符 * :間接訪問運算符 (1)上例將打印出i的值。(2)*pointer1 與普通的整型變量一樣使用,但前提是pointer1 必須已經明確地指向了某整型變量,或者說指針變量中必須已經存有了某整型變量的起始地址。 例如 i=3;pointer1=&i;printf(%d,*pointer1); 說明 3ipointer1*pointer1三、 指針變量(續)例1: 輸入兩
6、個整數,按先大后小輸出這兩個整數 #include int main() int *p1, *p2, *p,a,b; scanf(%d%d,&a,&b); p1=&a; p2=&b; /* 取變量的地址*/ if(ab) p=p1; p1=p2; p2=p; /* 指針變量間的相互賦值*/ printf(%d%d,a,b); printf(max=%d, *p1, *p2 ); return 0; 你能畫出程序中指針處理過程的示意圖嗎? 三、 指針變量(續)7.指針變量作為函數參數 函數的實參值是地址,函數的形參應定義為指針類型,此時,實參和形參之間仍然是傳值方式。參見例2。 #include
7、 void swap(int *p1, int *p2) int temp; temp=*p1; *p1=*p2; *p2=temp; int main() int a,b,*pointer1, *pointer2; scanf(%d%d,&a,&b); pointer1=&a; pointer2=&b; /* 取變量的地址*/ if(ab) swap(pointer1,pointer2); /* 函數調用,實參為指針變量*/ printf(%d%d,a,b);/* 打印函數調用后,變量a,b的值,觀察其變化*/ return 0; 在被調函數中,通過間接訪問,改變了主調函數中實參變量的值。變
8、量a,b的地址被傳遞到函數的形參變量p1,p2中四、數組與指針1.數組的存儲 數組在內存中占一片連續的存儲區,該存儲區的大小與數組的元素類型和數組長度有關。 每個數組元素占用相同大小的存儲空間。 利用數組存儲區的起始地址,可以逐個獲得每個數組元素的存儲地址。例如,定義數組 int a10; a0a1a2a3a4a5a6a7a8a9注:假設數組a的存儲區起始地址為2000。20002002 200420062000+4*22000+9*2由上圖可知,數組元素ai的存儲地址的計算公式為: 數組a的起始地址+i元素類型占內存的字節數圖2C語言規定: 數組名代表數組的起始地址,該地址在程序運行過程中不
9、能修改。 即數組名a是個常量。2.指向數組元素的指針 四、數組與指針例如, int a10; int *p;對指針變量p賦值:p=&a0; 則使p指向了數組的第一個元素。因此,下面對指針變量p賦值的兩個語句等價: p=&a0; p=a;因此定義指向數組的指針變量時,可以對其初始化: int a10;int *p=a; (或 int *p=&a0; )四、數組與指針例如,定義:int a10 ,*p=a; 可有如下操作: p=a; p=&a1; *p=10; 3.通過指針變量引用數組元素 4.指針變量表達式和指針的算術運算符 (1) 可以對指針進行有限的算術運算,包括自增運算(+)、自減運算(-
10、)、加上一個整數、減去一個整數,以及減去一個指針變量。(2)指針運算的結果依賴于指針所指向的對象的大小。指針的算術運算的規則是:當一個指針加上或減去一個整數時,指針并非簡單的加上或減去該整數值,而是加上或減去該整數與指針指向的對象的大小的乘積。例如:int a10 ,*p=a; 則 p=p+1; 使指針變量的值更新為數組元素a1的地址,即p指向了數組元素a1。注意:a+是錯誤的,為什么呢?例如:int a10 ,*p=a,*q,x;假定數組a的起始地址為2000,則下列每個操作后變量的值分別為多少?四、數組與指針p=p+1;q=p;q+=2;x=q-p;p+;+p;-p;p的值為2002,p指
11、向數組元素a1.q的值為2002, q指向數組元素a1.q的值為2006, q指向數組元素a3.x 的值為4 p的值為2004, p指向數組元素a2.p的值為2006 , p指向數組元素a3.p的值為2004, p指向數組元素a2.p-;p的值為2002, p指向數組元素a1.通過 - 運算,讓指針變量指向數組中的上一個元素。得到:從p到q的數組元素的個數通過+ 運算,讓指針變量指向數組中的下一個元素。指針的算術運算除了用于數組外沒有什么意義四、數組與指針5.指針和數組的關系C語言中數組與指針關系密切,它們幾乎可以互換。數組名可認為是一個常量指針,指針可以完成涉及數組下標的操作。例如:int
12、a10 ,*p=a;則,p指向數組的第一個元素,可用如下的指針表達式引用數組元素a3 *(p+3) 式中的 3 是對于指針變量p的偏移量。 當p指向數組的起始位置時,偏移量等于數組的下標。*(p+3) 這種表示法稱為“指針表示法” (或 *(a+3) )因為*的優先級高于+,所以圓括號是必需的。注意總結至此,引用一個數組元素,可以采用如下兩種方法之一:(1) 下標法: 如ai(2) 指針法:如 *(p+i) 或 *(a+i) 四、數組與指針例3:輸出數組中的全部元素。(采用三種方法輸出數組元素的值) #include int main() int a10 , i ; for(i=0; i10;
13、i+) scanf(%d,&ai); for(i=0; i10;i+) printf(%d,ai); return 0; #include int main() int a10 , i ; for(i=0; i10;i+) scanf(%d,&ai); for(i=0; i10;i+) printf(%d,*(a+i) ); return 0; #include int main() int a10 , i , *p; for(i=0; i10;i+) scanf(%d,&ai); for(p=a; p(a+10); p+) printf(%d, *p); return 0; 1.下標法2.
14、通過數組名計算數組元素的地址,找出元素的值3. 用指針變量指向數組元素(1)用下標法直觀;(2)用前兩種方法效率一樣; C編譯系統是將ai轉換為 *(a+i)來處理的(3)用第三種方法省時間, p+操作快。四、數組與指針6.用數組名作函數的參數(1) 實參數組名代表該數組首元素的地址。而形參是用來接收 從實參傳遞過來的數組首元素的地址。因此,形參應該是一個指針變量(只有指針變量才能存放地址)。 (2) 雖然函數 f 的原型為 void f( int arr, int n) ,但編譯時是將arr數組按指針變量來處理的。即:void f( int arr, int n) 與 void f( int
15、 *arr, int n) 等價 #include int main() int array10 ; . f(array,10); . void f( int arr, int n) . . 首先回顧第八章“函數”中介紹的數組名作函數參數的情形:規定:如果形參數組中元素的值發生變化,實參數組元素的值隨之變化。說明四、數組與指針例4.將數組a中n個元素按相反的順序存放。 #include void inv( int *x, int n) /* 形參為指針變量*/ int *p, temp,*i,*j, m=n-1/2; i=x; j=x+n-1; p=x+m; for(;i=p; i+,j-)
16、temp=*i; *i=*j; *j=temp; return; int main() int i,a10=3,7,9,11,0,6,7,5,4,2; for(i=0;i10;i+) printf(%d,ai); inv(a , 10 ); /* 函數調用,實參為數組名*/ for(i=0;i10;i+) printf(%d,ai); return 0; 3 7 9 11 0 6 7 5 4 2a0a1a2a3a4a5a6a7a8a9a 數組i, xp=x+mj圖3四、數組與指針例5.用選擇法對10個整數按由小到大順序排序。 #include void sort( int *x, int n)
17、 /* 形參為指針變量*/ int i,j,k; for(i=0;in-1; i+) k=i; for(j=i+1;j*(x+k) k=j; int main() int *p,i,a10; p=a; for(i=0;i10;i+,p+) scanf(%d,p); sort(p , 10 ); /* 函數調用,實參為指針變量*/ for(i=0, p=a;i10;i+,p+) printf(%d,*p); return 0; a0a1a2a3a4a5a6a7a8a9圖4a 數組x四、數組與指針7.指針和多維數組多維數組元素的地址假設有數組定義: int a34;C語言規定: (1) 二維數組的
18、起始地址為a; (2) 此二維數組由三個行元素組成:a0,a1,a2; (3) 每個行元素又是一個一維數組,包含4個元素: a0 為第一行的起始地址;a0 可用*a表示。 a1 為第二行的起始地址;a1 可用*(a+1)表示。 a2 為第三行的起始地址;a2 可用*(a+2)表示。 (4) 第0行第0列的元素a00的地址為: a0 ,也可用 *a表示。 第0行第1列的元素a01的地址為: a0+1,也可用 *a+1表示。 第0行第2列的元素a02的地址為: a0+2,也可用 *a+2表示。 第0行第3列的元素a03的地址為: a0+3,也可用 *a+3表示。 (5) 第0行第0列的元素a00可
19、表示為: *(a0),也可用 *(*a)表示。 第0行第1列的元素a01可表示為: *(a0+1),也可用 *(*a+1)表示。 第0行第2列的元素a02可表示為: *(a0+2),也可用 *(*a+2)表示。 第0行第3列的元素a03可表示為: *(a0+3),也可用 *(*a+3)表示。(6) 第1行第3列的元素a13可表示為: *(a1+3),也可用 *(*(a+1)+3)表示。把 a 看成一維數組時,按照前面給出方法表示一維數組的元素。 在C程序中,用兩種方法訪問字符串: (1)用字符數組存放一個字符串。 (2)用字符指針指向一個字符串。1.字符串的表示形式 五、字符串與指針 #inc
20、lude int main() char string=china! ; printf(%sn,string); return 0; #include int main() char *string=china! ; printf(%sn,string); return 0; (1)用字符數組存放一個字符串。(2)用字符指針指向一個字符串。用字符串常量初始化字符指針用字符串常量初始化字符數組五、字符串與指針2.訪問字符串中的字符 #include int main() char a=I love china! ,b20; int i; for(i=0;*(a+i)!=0; i+) *(b+i)
21、=*(a+i); *(b+i)=0; printf(%sn,b); return 0; 例6.將字符串a復制為字符串b。 3.字符串指針作函數參數 五、字符串與指針 #include void copy_string(char *from, char *to) for(; *from!=0; from+,to+) *to=*from; *to=0; int main() char a=I love china! ,b20; int i; copy_string(a,b); printf(%sn,b); return 0; 例7. 用函數調用實現字符串a復制。 此循環可改為:while(*to=*from)!=0)to+; from+;六、返回指針值的函數一個函數可以返回一個int型、float型、char型的數據,也可以返回一個指針類型的數據。 返回指針值的函數簡稱為指針函數。 舉例指針函數的定義 函數類型 *函數名(形參表)定義形式int *func(int x , int y ) char *string; . return(string);指向函數的指針函數指針如果在程序中定義了一個函數,在編譯時,編譯系統為函數代碼分配一段存儲空間,這段存儲空間的起始地址(又稱入
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 自動控制器項目投資立項申請
- 璀璨未來·醫院搬遷慶典活動全紀實
- 部編版五年級下冊第五單元《人物描寫一組》教案
- 建筑施工特種作業-樁機操作工真題庫-2
- 弱智化學題目及答案
- 2023-2024學年云南省曲靖市會澤縣高二下學期期末考試數學試卷(解析版)
- 2023-2024學年四川省德陽市高二下學期期末數學試題(解析版)
- 高校學生傷害事故及其法律責任淺析
- 新疆藍潔環保科技有限公司廢油再生循環及廢舊包裝桶回收、無害化處理綜合利用項目環境影響報告書
- 傳統藥物安全合作協議
- 中國華電集團公司信訪事項處理程序
- 特種設備制造內審及管理評審資料匯編經典版
- 教師壓力管理(教育心理健康C證培訓)課件
- 工程勘察設計收費標準使用手冊
- 網絡暴力主題班會PPT課件講義
- 《工程管理指導書》word版
- 合理低價法得分計算
- 關于涉農企業稅收風險管理的實踐和思考
- 05S502閥門井圖集
- 輪扣式支架模板施工方案
- 雙門通道控制(共20頁)
評論
0/150
提交評論