信管C基礎第10章-指針.ppt_第1頁
信管C基礎第10章-指針.ppt_第2頁
信管C基礎第10章-指針.ppt_第3頁
信管C基礎第10章-指針.ppt_第4頁
信管C基礎第10章-指針.ppt_第5頁
已閱讀5頁,還剩111頁未讀 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

1、第十章 指針,10.1 地址和指針的概念 數(shù)據(jù)在內(nèi)存的存放、讀取方式(以變量為例):,用戶在程序設計中定義一個變量,內(nèi)存區(qū)每一個字節(jié)有一個編號地址,編譯過程中: 1、根據(jù)變量類型,分配一定長度的內(nèi)存空間; 2、變量名轉(zhuǎn)換為所分配內(nèi)存的地址,2、用戶存取數(shù)據(jù)方式,變量名,地址,地址所標志的內(nèi)存段,1、數(shù)據(jù)使用前的編譯處理過程,數(shù)據(jù),一個比方: 旅 客 變量數(shù)據(jù) 旅 客 名 字 變量名 旅館房間 內(nèi) 存 區(qū) 旅館房間號 地 址 查找旅客:旅客名字房間號碼房 間找到旅客 存取數(shù)據(jù): 變量名 內(nèi)存地址內(nèi)存區(qū)數(shù) 據(jù) 注意: 內(nèi)存單元的地址與內(nèi)存單元的內(nèi)容是不同的。 內(nèi)存單元地址旅館房間號碼 內(nèi)存單元內(nèi)容

2、住在房間內(nèi)的旅客。,內(nèi)存地址,內(nèi)存用戶數(shù)據(jù)區(qū),內(nèi)存中存放的數(shù)據(jù),3、數(shù)據(jù)存取舉例 設程序中已定義三個整型變量 i, j , k,編譯時系統(tǒng)將2000和 2001兩個字節(jié)給變量i ,2002、2003給j,2004、2005給k。內(nèi)存 分配示意圖如下,內(nèi)存地址,內(nèi)存用戶數(shù)據(jù)區(qū),printf (“%d”,i) 變量名i 地址2000 取變量值3 送到輸出設備 k = i + j 變量名i 地址2000 取變量值3 變量名j 地址2002 取變量值6,相加得9 送到K占用的2004,2005,4、直接訪問與間接訪問 直接訪問: 在數(shù)據(jù)存取中,直接得到變量 i 地址然后 按變量 i 的地址存取變量 i

3、 的值的方式。 間接訪問: 在數(shù)據(jù)存放中,變量 i 的地址不是直接得到, 而是存 放在另一個變量i_pointer中,須先從變量i_pointer中 獲取變量 i 地址,然后按變量i地址存取變量值i的方式。,一個比方(取抽屜A中的東西): 直接訪問: 直接得到鑰匙A 打開抽屜A,取出東西 (直接獲得變量 i 地址按變量 i 地址存取變量的 i 值 ) 間接訪問: 鑰匙A在抽屜B中用鑰匙B打開抽屜B得到鑰匙A打開抽屜A取得東西,變量i地址放在 變量i_pointer中,讀取變量i_pointer 值得到變量i的地址,按變量i地址存取i值,*間接訪問例子 過程:根據(jù)變量名i_pointer獲得地址

4、3010,到地址3010 讀取數(shù)據(jù),得到2000(變量i的地址),到2000地 址讀取數(shù)據(jù),得到變量i的值。,內(nèi)存地址,內(nèi)存用戶數(shù)據(jù)區(qū),5、指針和指針變量 指針:一個變量的在內(nèi)存區(qū)中的地址稱為指針。通過變量的指 針,可以找到變量的存儲單元,從而讀取其中存放的值; 指針變量:專門用來存放指針的變量,稱為指針變量。指針變 量存放的數(shù)據(jù)為另一變量的地址(指針)。 注意:指針與指針變量的區(qū)別 指針是一個地址,用于指向存放變量數(shù)據(jù)的內(nèi)存單元; 指針變量是一個變量,它的值是指針 例如:變量 i 的地址2000為該變量的指針,變量i_pointer是 用來存放 變量i的指針的,它是一個指針變量。,對地址的操

5、作,之前我們可以通過 變量j 中存放的是一個數(shù),是i的地址 但我們要如何才能把一個數(shù)如 200 存放到變量i所在的內(nèi)存中呢?,最簡單的方式 i=200; 這是賦值語句,編譯器會自動的把200送到i所在的內(nèi)存單元 但我們?nèi)绾螌崿F(xiàn)直接對地址操作?,j = 200;,不可行。此語句是把200送到變量j所在內(nèi)存單元,對變量i沒有任何影響,指針,C語言和其他語言的一個重要區(qū)別在于:C語言提供了一種方法,使程序員可以不通過變量名,而通過變量地址直接對變量所在的內(nèi)存單元進行操作。這樣,C語言就有了低級語言的特性,直接對地址進行操作也更高效。 C中要直接對地址(內(nèi)存)進行操作,需要使用指針變量,10.2 變量

6、的指針和指向變量的指針變量,指針:它首先是一個地址,是指變量在內(nèi)存中的地址 ; 指針變量:它是一個變量,是一個專門存放變量地址的 變量,用來指向另一個變量。 變量都是有類型的,如int ,float,這里可以理解為:現(xiàn)在有一種變量,它存放的數(shù)據(jù)對CPU而言表示為“地址”,但要明白,不管是什么,都是一個“二進制”,地址也是一個數(shù)。 指針變量的出現(xiàn),解決了對內(nèi)存操作的問題: 為了表示指針變量和它所指向的變量之間的聯(lián)系, 在程序中用“”表示“指向” 例:假設i_pointer代表指針變量,它有一個值,這個值就是某個變量的地址;而 *i_pointer 是i_pointer所指向的變量。所謂的“指向”

7、就是 i_pointer 的值所在的內(nèi)存單元,見下圖,指針和指向,int i; int * i_pointer; 定義一個指針變量 i=3; i_pointer=,分配一塊2字節(jié)的內(nèi)存,假設地址為2000,并用符號i表示這個地址,分配一塊2字節(jié)的內(nèi)存,假設地址為2004,并用符號i_pointer代表這個地址,i3; 然后把3寫入i的地址,就是寫到內(nèi)存2000處,i_pointer= 然后把i的地址2000寫入i_pointer的地址,就是寫到內(nèi)存2004處,指針和指向,i_pointer,C語言提供一種特殊的表示方式: i_pointer 用它表示i_pointer所指向的內(nèi)存單元,2000

8、,3,內(nèi)存2000,i,i_pointer與 i 是等效的,都表示同一變量,該變量存放地址為2000。因此: i5; i_pointer5 兩語句作用相同,后者直接操作內(nèi)存,內(nèi)存2004,現(xiàn)在,內(nèi)存中的情況如下,我們稱:i_pointer指向變量i,為什么?,i_pointer存放i的地址,通過i_pointer,可以找到i,問題:如何給i賦值為5?,i_pointer = 5;,5,*i_pointer = 5; 把5寫入到i_pointer所指向的內(nèi)存單元,5,10.2.1定義一個指針變量,例: int i, j ; int pointer_1 , pointer_2 ; 第一條命令定義了

9、兩個整型變量 i, j; 第二條命令定義了 兩個指針變量 pointer_1, pointer_2,它們指向整型變量; 兩個整型變量pointer_1, pointer_2,它們與 i,j為相同類型,被pointer_1, pointer_2兩個指針所指向;,基類型: 指針變量的基類型是指該指針變量可以指向的變量的類型; 定義指針變量的一般形式: 基類型 指針變量名 例: float pointer_3; (pointer_3是指向?qū)嵭妥兞康闹羔樧兞?,即其中存放的應該是一個float類型變量的地址) char pointer_4; (pointer_4是指向字符型變量的指針變量),指針變量指向

10、的改變: 方法:將一個該指針允許指向的變量的地址賦給該指針;,pointer_1= 為整型指針變量 float f; p = 都為非法賦值。實際運行時,編譯器只提出警告,程序仍可以運行,但是往往會導致系統(tǒng)錯誤。- “該程序執(zhí)行了非法操作” . 遇到問題問題需要關閉,我們對此引起的不便表示抱歉,思考,指針變量也是變量,指針變量占多少字節(jié)呢?它的大小又有什么含義呢?,在16位計算機中指針是2字節(jié),在32位計算機中是4字節(jié):4字節(jié)表示指針變量i_pointer占4字節(jié),而不管它所指向的是什么,即指針變量只和編譯器相關,和指向類型無關,指針的大小表示了它的”尋址能力“,4字節(jié)最多可以表示的地址是:0

11、xffffffff,即2324G,指針的運算符,有關的兩個運算符: (1) 例程說明 例,二. 指針變量的引用 例10.1 main( ) int a , b ; int *p1 , *p2 ; a = 100 ; b = 10 ; p1 = /*間接訪問 結(jié)果: 100 , 10 100 , 10 程序中: *p1表示指針變量 p1所指向的變量,即 a . *p2表示指針變量 p2所指向的變量,即 b .,p1,a, p1 = 則: (*p1) + + 等價于 a + + 但注意 *p1+ + 不等價于 (*p1) + +, scanf ( “ %d , %d ” , 如輸入: 5 , 9

12、,輸出: a = 5 , b = 9 max = 9 , min = 5 ( 注意: 本程序是采用交換變量 a 和 b 的地址來實現(xiàn)兩個數(shù)的比較的.且比較前后 a , b 的值并未發(fā)生變化 ), p = p1 ; p1 = p2 ; p2 = p ; main( ) int a , b; scanf ( “ %d , %d ” , ,為什么C語言不讓實參和形參雙向傳遞呢? 這種情況會出錯: swap( 2, 3); 大多數(shù)情況, 函數(shù)參數(shù)都是單向傳遞的, 通過返回值得到結(jié)果, 這樣更符合結(jié)構(gòu)化程序設計的思想, 在不主動要求改變的情況下, 函數(shù)不應該改變實參的值, 否則可能導致程序設計時情況變得

13、復雜,三. 指針變量作為函數(shù)的參數(shù) 指針變量可以作函數(shù)的參數(shù),其作用是將一個變量的地址傳送到另一個函數(shù)中。 例 10.3 swap (int * p1 , int * p2 ) int p ; p = *p1 ; *p1 = *p2 ; *p2 = p ; main( ) int a=1, b=2 , *pa , *pb ; pa = ,swap (int * p1 , int * p2 ) int p ; p = *p1 ; *p1 = *p2 ; *p2 = p ; main( ) int a=5, b=9 , *pa , *pb ; pa = ,a,b,pa,p1,p2,p,00,02,

14、04,08,0a,0c,pb,5,9,06,00,02,調(diào)用swap交換,00,02,5,9,5,如果把 swap 函數(shù)改成 : swap (int * p1 , int * p2 ) int *p ; *p = *p1 ; (此句有問題 ) *p1 = *p2 ; *p2 = * p ; 又如: swap ( int x , int y ) int t ; t = x ; x = y ; y = t ; ,P無確定的地址值,它的的值不可預見,*p所指向的單元也是不可預見,對*p賦值可能會破壞系統(tǒng)的正常狀態(tài)。,注意參數(shù)的傳遞類型為“值傳遞”,說明: 1. 不能通過改變形參指針變量的值而使實參指

15、針變量的值改變. 2. 可以通過改變形參指針變量所指向的變量的值來改變實參指針變量所指向的變量的值. 3. 如想通過函數(shù)調(diào)用得到 n 個要改變的值,可以: (1) 在主調(diào)函數(shù)中設 n 個變量,并用 n 個指針變量指 向它們; (2) 將指針變量作實參,使 n 個變量的地址傳給所調(diào)用的函數(shù)形參; (3) 通過形參指針變量,改變該 n 個變量的值; (4) 主調(diào)函數(shù)中就可以使用這些改變了值的變量。,swap (int * p1 , int * p2 ) int *p ; p = p1 ; p1 = p2 ; p2 = p ; main( ) int a=1, b=2 , *pa , *pb ; p

16、a = ,本函數(shù)中試圖通過改變形參指針變量的值來使實參指針變量的值改變.,swap (int * p1 , int * p2 ) int *p ; p = p1 ; p1 = p2 ; p2 = p ; main( ) int a=1, b=2 , *pa , *pb ; pa = ,a,b,pa,p1,p2,p,00,02,04,08,0a,0c,pb,1,2,06,00,02,調(diào)用swap交換,00,02,交換p1,p2的值,02,00,雖然改變了“指向”,但沒有改變實參的值,即Pa和Pb沒變,a,b也沒有變,printf ( “%d %d n ”, *pa , *pb ) ;,總結(jié):指針

17、(地址)做為函數(shù)參數(shù)的意義:,因為變量的作用域的關系, 調(diào)用函數(shù)和被調(diào)用函數(shù)中的變量盡管名字可以相同, 但內(nèi)存地址不同. 實參和形參的內(nèi)存地址也不同, 而且是”單向傳遞”,想要通過形參改變而影響實參是做不到的, 要在被調(diào)用函數(shù)中通過”變量名”對調(diào)用函數(shù)中的變量操作也不可行. 唯一的辦法是, 在被調(diào)用函數(shù)中直接對”調(diào)用”函數(shù)中變量的”內(nèi)存地址”操作. 可行的原因在于”函數(shù)”中局部變量的”生存期”是隨著函數(shù)的消亡而消亡的, 主調(diào)函數(shù)還沒有結(jié)束時, 其中的局部變量仍然存在于內(nèi)存中, 只是由于種種原因,通過變量名無法訪問. 最終的手段是直接操作地址, 而函數(shù)間的通信可以通過參數(shù)傳遞, 所以, 把地址做

18、為參數(shù)就達到了我們的目的,思考:既然這樣,假設知道了”被調(diào)用函數(shù)”中某個變量地址, 我們是否可以直接在”主調(diào)用函數(shù)”中直接對”被調(diào)用函數(shù)”中的變量進行操作呢?,#include int* test(int x) int k=111; return ,#include int* test(int x) int k=111; return ,什么時候需要地址傳遞:,1. 傳遞整個數(shù)組 2. 需要在被調(diào)用函數(shù)中修改調(diào)用函數(shù)中的變量 3. 需要多個”返回值”,但不想使用全局變量, 可以在調(diào)用函數(shù)中設置多個指針, 而被調(diào)用函數(shù)中則把要”返回的值”寫入到相應的內(nèi)存地址,例 10.4輸入a,b,c3個整數(shù),

19、按大小順序輸出 swap ( pt1 , pt2 ) int *pt1 , *pt2 ; int p ; p = *pt1 ; *pt1 = *pt2 ; *pt2 = p ; exchange (int *q1, *q2 , *q3 ;) if (*q1 *q2) swap ( q1 , q2 ) ; if (*q1 *q3) swap ( q1 , q3 ) ; if (*q2 *q3) swap ( q2 , q3 ) ; main ( ) int a , b , c , *p1 , *p2 , *p3 ; scanf ( “ %d , %d , %d ”, ,10.3 數(shù)組的指針和指向

20、數(shù)組的指針變量,C語言中,指針變量可以指向變量,也可以指向數(shù)組和數(shù)組元素. 數(shù)組的指針: 數(shù)組的起始地址. 數(shù)組元素的指針: 數(shù)組元素的地址. 一.指向數(shù)組的指針變量的定義與賦值 指向數(shù)組的指針變量的定義同指向變量的指針變量的定義相同. 如: int a10 ; int * p ; 若: p = 的含義是將數(shù)組首地址賦給指針變量 p ,而不是賦給 ( *p ).,二. 通過指針引用數(shù)組元素 如: int a10 , *p ; p = a ; 則: (1) p a0的地址; p + 1 a1的地址; p + i ai的地址. (2) *p = = a0 , *(p +1) = = a1 , *(

21、p +i) = = ai 說明: 1. 數(shù)組元素在內(nèi)存中是連續(xù)存放的,C語言規(guī)定,指針變量 p + 1 指向下一個元素 (不是簡單的加 1 ).,2. ( p + i ) 表示指向 ai 的地址, 而 a + i 也表示 ai 的地址,故 程序中( p + i ) 等價于a + i . 如: p + 2 ; a + 2 ; 3. 指向數(shù)組的指針變量可以帶下標. 如: pi *(p +i),a數(shù)組,p,p+1,a+1,p+i ,a+i,p+9 ,a+9,a0,a1,ai,a9,*(p +i),綜上所述: 數(shù)組元素的引用可以: (假定: int a10 , *p = a ; ) (1) 下標法:

22、數(shù)組名下標 或 指針變量名下標 ai pi (2) 指針法: *(p +i) 或 *(a +i),思考: 數(shù)組的指針 和 數(shù)組名有何異同?,int a10 ,b10 , *p = a ;,相同點: p和a都表示地址,都可以進行地址的運算,如:p+1, a+1, p5, a5, *a 等,不同點: p是變量,可以被改變。而數(shù)組名a是“常量”,只能引用不能被改變(賦值),p+1, a+3, p+ 可以, a+ 錯 p=p3;可以, a = a+3錯 p = b; p= for ( i = 0 ; i 10 ; i + + ) scanf ( “ %d ”, ,例 10.5 用四種方法輸出數(shù)組各元素

23、. (3)指針下標 main ( ) int a10 , i , *p=a; for ( i = 0 ; i 10 ; i + + ) scanf ( “ %d ”, ,main( ) int a10 , i , *p=a; for ( i = 0 ; i 10 ; i + + ) scanf ( “ %d ”, p+i ) ; 注意是p+i不是 ,思考:既然指針可以替代數(shù)組,那么上面的程序中是否可以省略掉數(shù)組定義,只使用指針呢?像下面這樣:,main( ) int i , *p; for ( i = 0 ; i 10 ; i + + ) scanf ( “ %d ”, p+i ) ; for

24、 ( i = 0 ; i 10 ; i + + ) printf ( “%d ”, *(p +i) ) ; ,指針指向不確定 即使指針指向確定,但系統(tǒng)只給指針分配了一塊內(nèi)存,只有這塊內(nèi)存才可以“安全,合理”使用的 如果有一塊連續(xù)的安全內(nèi)存可用,當然可以不用數(shù)組 注意上面條件,“連續(xù)”,如果不連續(xù),又有什么問題?,注意幾點:,(1) 指針變量可以作自增,自減運算. 如: + + p , p . 而數(shù)組名不能作自增,自減運算. 如 a + + , a 等, 均不合法.因為數(shù)組名是常量. (2) 注意指針變量的當前值. 如: 例 10.6: main( ) int a10 , i , *p ; p

25、= a ; for ( i = 0 ; i 10 ; i + + ) scanf ( “ %d ”, p+ ) ; printf ( “ n” ) ; for ( i = 0 ; i 10 ; i+ , p+ ) printf ( “%d ”, *p ) ; ,(3) 注意指針變量的運算. 如: int a10 , i , *p ; p = a ; 則: a. p+ (或 p+=1 ) 表示 p 指向 a1 , 此時若執(zhí)行*p ,則 取出 a1 元素的值. b. “*” 與 “+ +” 同優(yōu)先級,自右往左結(jié)合. 如: *p+ + 等效于 *(p+ + ) , 即先取 p 所指向變量的值, 再使

26、 p + 1 . 而 *(p + + ) 與*(+ + p ) 的作用不同.前者先取*p 的值,后使p + 1 ; 后者是先使 p + 1 ,再取*p的值 . (*p)+ + 表示使目標變量的值加 1 . 而不是指針變量的值加 1。,e. *(p + + ) 等價于 ai + + . *(+ + p ) 等價于 a+ + i 即先使 p 自增,再作 * 運算. 如: main( ) int a100 , *p ; p = a ; while ( p a +100 ) printf ( “ %d ”, *p + + ) ; main( ) int a100 , *p ; p=a; while (

27、 p a +100 ) printf ( “ %d ”, *p ) ; p + + ; ,三. 數(shù)組名作函數(shù)參數(shù),數(shù)組名作函數(shù)參數(shù)時,實際上是將實參數(shù)組的首地址傳給形參。這樣實參數(shù)組與形參數(shù)組共占同一段內(nèi)存。使得在 調(diào)用函數(shù)過程中,形參數(shù)組中元素值發(fā)生變化也就使實參數(shù)組的元素值隨之而發(fā)生變化。,如: main( ) int array10 ; f ( array , 10 ) ; f( arr , n ) int arr , n ; ,arr,1)實參傳遞給形參后arr和arry指向同一內(nèi)存地址; 2)將“10”傳遞給形參n后,界定了形參數(shù)組的范圍; 3)這種“數(shù)組名數(shù)組元素個數(shù)”的參數(shù)形式是

28、常用的。,例 10.7 將數(shù)組 a 中 n 個整數(shù)按相反順序存放. 題意分析: 本題的關鍵是最后交換的兩個元素的上下標值的確定。即將第一個元素和最后一個元素對換,將第二個同倒數(shù)第二個對換. .即兩兩對換,直到:a (n 1) /2 與 an int( n 1 ) / 2) 對換為止。其中an int( n 1 ) / 2) 與an 1 ( n 1 ) / 2)等效。,void inv( x , n ) int x , n ; int t ,i,j,m=(n 1)/2; for( i=0; i=m ; i+ + ) j = n1i; t = xi; xi = xj; xj = t ; retur

29、n; main( ) static int i , a10 = 3,7,9,11,0,6,7,5,4,2 ; printf ( “ The original array : n ” ) ; for ( i = 0 ; i10 ; i+ ) printf ( “ %d ”, ai ) ; printf ( “ n ” ) ; inv ( a , 10 ) ; printf ( “ The array has been inverted : n ” ) ; for ( i = 0 ; i 10 ; i + + ) printf ( “ %d ”, ai ) ; printf ( “ n ” ) ;

30、 ,例10.8 從 10 個數(shù)中找出其中最大值和最小值 int max , min ; void max_min_value (int array , int n ) int *p , *array_end ; array_end = array + n ; max = min = *array ; for ( p=array+1; pmax ) max = *p ; else if( *p min ) min = *p ; main( ) int i, number10 ; printf ( “ enter 10 data n ”) ; for( i=0; i10; i+ ) scanf (

31、 “ %d ”, ,等效于 *(array + 0) 即 array0,此例也可改用指針變量來傳送地址,程序可改為: int max , min ; void max_min_value (int * array , int n ) int *p , *array_end ; array_end = array + n ; max = min = *array ; for( p = array + 1 ; p max ) max = *p ; else if ( *p min ) min = *p ; return ; main( ) int i , number10 , *p ; p=num

32、ber ; printf ( “ enter 10 data n ”) ; for ( i = 0 ; i 10 ; i + + , p + + ) scanf ( “ %d ”, p ) ; printf ( “ the 10 data : n ” ) ; for(p=number, i=0; i10; i+, p+ ) printf( “%d”, *p ) ; p=number ; max_min_value( p , 10 ) ; printf ( “ n max = %d , min = %d n ”, max , min ) ; ,for(p=number;p(number+10);

33、p+) 等效于:,不使用全局變量 void max_min_value (int * array , int n , int* max,int* min; ) int *p , *array_end ; array_end = array + n ; max = min = *array ; for( p = array + 1 ; p *max ) *max = *p ; else if ( *p *min ) *min = *p ; main( ) int i , number10 , max , min; for ( i = 0 ; i 10 ; i + + , p + + ) scan

34、f ( “ %d ”, ,數(shù)組名是地址, 故可以傳送給 int * array,綜上所述,對于實參數(shù)組,想在被調(diào)函數(shù)中改變此數(shù)組元素的值,實參與形參的對應關系可以如下:,(1) 二者都用數(shù)組名 main ( ) int a10; f( a, 10 ); f( x, n) int x , n ; 特點: a 和 x 數(shù)組共用同一段內(nèi)存單元。,(2) 實參為數(shù)組名,形參用指針變量. main ( ) int a10 ; f( a,10); f( x, n ) int *x , n ; 特點: 實參將數(shù)組的首地址傳給形參指針變量,通過指針變量指向數(shù)組中的任一元素,進而作相應的處理。,(3) 二者都用

35、指針變量。 main ( ) int a10 , *p ; p = a ; f ( p , 10 ) ; f( x , n ) int *x , n ; 特點: 先使 p 指向 a 數(shù)組,再將 p 傳給 x , 使 x 也指向 a 數(shù)組,從而進行處理.,(4)實參為指針變量,而形參為數(shù)組名。 main ( ) int a10 , *p ; p = a ; f ( p , 10 ) ; f( x , n ) int x , n ; 特點:利用指針變量將 a 數(shù)組的首地址傳給 x 數(shù)組.使兩數(shù)組共用同一段內(nèi)存單元.利用xi值的變化,使ai的值也發(fā)生變化.,注意: 在上述四種處理方式中,當用指針變量

36、作實參時,必須先使指針變量有確定的值,即指向一個已定義的數(shù)組。,四、 指針與二維數(shù)組,1、指針與二維數(shù)組 一個數(shù)組的名字代表該數(shù)組的首地址,并可看成是地址常量,這一規(guī)定對二維數(shù)組或更高維數(shù)組同樣適用。 若有定義: float *p, d35; 則:,2. 二維數(shù)組元素和二維數(shù)組元素的地址,假設數(shù)組名為a,起始地址設為200 int a34=1,3,5,7,9,11,13,15,17,19,21,23; 則: a代表整個二維數(shù)組的首地址,即第0行的首地址 a+1是數(shù)組a第1行首地址(208) a0,a1,a2是二維數(shù)組中三個一維數(shù)組的名字(地址),是第0行,第1行,第2行的首地址,即:a0=a+

37、0、a1=a+1、a2=a+2 ai+j是第i行j列的地址 *(ai+j)是該地址存儲的值, 即aij 考慮 *(a2+3)=?,注意:,ai和*(a+i)無條件等價 a+i、ai、*(a+i)、 main( ) int *p, a34, b34, c34; printf(The value of a:n); for(i=0; i3; i+) for(j=0; j4; j+) scanf(%d,ai+j); printf(The value of b:n); for(i=0; i3; i+) for(j=0; j4; j+) scanf(%d, *(b+i)+j); matrix(*a, b0

38、, ,matrix(int *x, int *y, int *z) for(i=0; i3; i+) for(j=0; j4; j+) *(z+i*4+j)= *(x+i*4+j)+*(y+i*4+j); ,數(shù)組元素在內(nèi)存中按“行優(yōu)先”的順序存放,因此可用x+i*4+j表示二維數(shù)組各元素的地址,10.4 字符串的指針和指向字符串的指針變量,字符串的指針就是字符串的首地址. 一. 字符串的表示形式 1: 用字符數(shù)組實現(xiàn) 例 10.16 main ( ) static char string = “ I Love China ” ; printf ( “ %sn ” , string ) ; 例中

39、 string 是數(shù)組名, 它表示字符數(shù)組的首地址。相應的 streingi 表示數(shù)組中的一個元素. 如:string4 代表第五個元素,即 字母 v 。,2. 用字符指針實現(xiàn) 例 10.17 main( ) char *string = “ I Love China ” ; printf ( “ %sn ” , string ) ; 例中 string 是一個指向字符串的指針變量。盡管程序中沒有直接定義字符型數(shù)組,但實際上,C語言對字符串常量均按字符數(shù)組來處理.即在內(nèi)存中開辟了一個字符數(shù)組用來存放字符串常量.,另外, char *string = “ I Love China ” ; 等價于

40、以下兩條語句: char *string ; string = “ I Love China ” ; 其含義是將字符串的首地址賦給指針變量 string。 注意: C語言中對字符串可以進行整體輸入和輸出. 而對數(shù)值型數(shù)組則不能用數(shù)組名來輸出它的全部元素,只能逐個元素輸出. 如: int a ; printf ( “%d n ”, a ) ;,( 不行 ),思考:這樣”規(guī)定”的原因,因為字符串有結(jié)束符號0,只要給出首地址, 就可以連續(xù)輸出, 遇到結(jié)束符結(jié)束. 但如果是數(shù)值型的數(shù)組, 系統(tǒng)就不知道數(shù)組的長度, 何時結(jié)束,對字符串的處理可以用下標法也可用指針法,例 10.18 將字符串 a 復制到字

41、符串 b . main ( ) char a =“ I am a boy.”,b20; for( i=0; *(a+i)!=0; i+) *( b+i )=*( a+i ); *( b+i )=0; printf(“ string a is : %sn”, a); printf ( “ string b is : ” ); for ( i=0; bi !=0; i+) printf( “ %c ”, bi); printf( “n”); 運行結(jié)果: string a is : I am a boy . string b is : I am a boy .,例 10.19 用指針變量來處理例 1

42、0.18(復制) 問題. main( ) char a =“ I am a boy.”,b20,*p1,*p2; int i; p1=a; p2=b; for( ;*p1!=0; p1+,p2+) *p2=*p1 ; *p2=0 ; printf( “string a is:%sn ”, a); printf( “string b is:” ); for( i=0 ; bi!=0; i+) printf(“ %c ”, bi); printf(“ n” ) ; ,二. 字符串指針作函數(shù)參數(shù),用字符數(shù)組名和指向字符串的指針變量作函數(shù)參數(shù),均可以處理字符串。 例 10.20 用函數(shù)調(diào)用實現(xiàn)字符串的

43、復制. (1) 用字符數(shù)組作函數(shù)參數(shù) void copy_string( char from , char to ) int i=0; while( fromi!=0 ) ( 先判斷,后賦值 ) toi=fromi; i+; toi=0 ; main ( ) char a =“ I am a teacher.”; char b =“ you are a student.”; printf(“ string_a=%sn string_b=%sn”, a, b); copy_string( a, b) ; printf(“ n string_a=%sn string_b=%sn”, a, b);

44、,void copy_string( char from , char to ) int i=0; while( fromi!=0 ) toi=fromi; i+; toi=0 ; main ( ) char a =“you are a student.”; char b =“ I am a teacher.”; copy_string( a, b) ; printf(“a=%sn b=%sn”, a, b); ,字符串a(chǎn)比字符串b長, 把a拷貝到b, 裝不下 且注意: a,b在內(nèi)存中是連續(xù)存放的,b在高地址,a在低地址, 復制時會導致a原來的內(nèi)容被沖掉,本程序 main 函數(shù)中也可用字符型指

45、針變量. 改寫如下: main( ) char *a=“ I am a teacher.”; char *b=“ you are a student.”; printf (“ string_a=%sn string_b=%sn ”, a, b); copy_string(a, b); printf(“n string_a=%sn string_b=%sn”,a, b); ,(2) 形參用字符指針變量 void copy_string(char *from,char *to) for( ;*from!=0;from+, to+ ) *to=*from; *to=0; main ( ) char

46、*a=“ I am a teacher .” ; char *b=“ you are a student .” ; printf(“string_a = %sn string_b = %sn ”,a,b); copy_string ( a , b ) ; printf(“n string_a = %sn string_b = %sn ”,a,b); ,(3) 對 copy_string 函數(shù)的簡化 a . void copy_string(char *from,char *to) while ( (*to = *from ) ! = 0 ) from+ ; to+ ; 即先賦值,后判斷, 故*

47、to=0語句 不要 . b. void copy_string(char *from,char *to) while ( (*to+=*from+ ) ! = 0 ) ; ,注意,c. void copy_string(char *from,char *to) while ( *from!= 0 ) *to+ = *from+ ; *to=0 ; d. void copy_string(char *from,char *to) while( *from ) *to+ = *from+; *to=0 ; ,e. void copy_string(char *from,char *to) whil

48、e ( *to + + = *from + + ) ; f. void copy_string(char *from,char *to) for ( ; (*to+=*from+)!=0;) ; ,for ( ; *to + + = *from + + ; ) ;,綜上所述,用函數(shù)調(diào)用來處理字符串時,函數(shù)參數(shù)可以有以下幾種情況: 實參 形參 1. 數(shù) 組 名 數(shù) 組 名 2. 數(shù) 組 名 字符指針變量 3. 字符指針變量 字符指針變量 4. 字符指針變量 數(shù) 組 名,三. 字符指針變量與字符數(shù)組的區(qū)別 1. 字符數(shù)組由若干個元素構(gòu)成,每一個元素中存放一個字符.而字符指針變量中存放的是字符串的首

49、地址。絕非將字符串放在字符指針變量中. 2. 賦值方式可以不同. 如: char str = “ Hellow ” ; char *a = “ Hellow ” ; 對指針變量也可以: char *a ; a = “ Hellow ” ; 而: char str10 ; str = “ Hellow ” ;,合法,不合法,3. 數(shù)組定義后,在編譯時就已分配內(nèi)存單元,即由確定的值 而對指針變量定義后,盡管系統(tǒng)給其分配了內(nèi)存單元,但 在沒有明確指向前,其值是不確定的。 如: char str10 ; scanf ( “ %s ”, str ) ; 而: char *a ; scanf ( “ %s

50、 ”, a ) ; 可改為: char *a str10 ; a = str; scanf ( “ %s ”, a ) ; 注意:char *a ; a = “ Hellow ” ;,合法,不合法,合法,為什么?,只要是”字符串,就是常量,編譯器會把常量分配在內(nèi)存的常量區(qū), 把首地址賦給a, 這樣又會帶來什么問題?,以下程序有錯誤,char a*; a=“hello”; *(a+1)=o; puts(a);,*(a+1)=o; a指向的是內(nèi)存”常量區(qū)”地址, 不允許對常量區(qū)進行寫操作, 但是讀是可以的.如: char d=*a;,4. 指針變量的值可以改變,而數(shù)組名則不行. 例10.21 ma

51、in ( ) char *a=“ I love China ! ” ; a=a+7; printf ( “ %s ”, a ) ; 運行結(jié)果: China ! 而下面程序則是錯的: main( ) char str = “ I love China ! ” ; str = str + 7 ; printf ( “ %s ”, str ) ; 可改為: main ( ) static char str = “ I love China ! ” ; printf ( “ %s ”, str + 7 ) ; ,例 10.22 (p195) main ( ) char *a = “ I LOVE CH

52、INA. ” ; int i ; printf (“ The sixth character is %c n ”, a5 ) ; for ( i = 0 ; ai ! = 0 ; i + + ) printf ( “ %c ” , ai ) ; 運行結(jié)果: The sixth character is E I LOVE CHINA.,指針變量帶下標方式引用字符等價于 *( a + i ),5. 可用指針變量指向一個格式字符串,用以代替 printf 函 數(shù)中的格式控制. 如: char *format ; format = “ a = %d , b = %f n ” ; printf ( fo

53、rmat , a , b ) ; 當然也可用字符數(shù)組. 如: char format =“ a = %d , b = %f n ” ; printf ( format , a , b ) ; 由于不能對字符數(shù)組整體賦值,所以用指針變量就更方便靈活. char *format ; format = “ a = %d , b = %f n ” ; printf ( format , a , b ) ; format = “ c = %c , d = %u n ” ; printf ( format , c , d ) ; ,10.5 函數(shù)的指針和指向函數(shù)的指針變量,一.用函數(shù)指針變量調(diào)用函數(shù) 函數(shù)

54、的指針: 函數(shù)的入口地址 函數(shù)的指針變量: 指向函數(shù)入口地址的指針變量 一個已定義的函數(shù)在編譯時,系統(tǒng)為其分配一個入口地址,并用函數(shù)名表示。通過指向函數(shù)的指針變量,也可以調(diào)用函數(shù). 指向函數(shù)的指針變量的一般定義形式: 數(shù)據(jù)類型 (*標識符) ( ) ; 其中: 數(shù)據(jù)類型是指函數(shù)返回值的類型. 如: int (*p ) ( ) ; 注意定義時也有優(yōu)先順序,根據(jù)右結(jié)合原則. 定義了一個標識符p, p是什么? 根據(jù)*p知道,是指針變量. 而指針變量有類型, 這里是p指向的是一個函數(shù), 這個函數(shù)的返回值是整型, 沒有參數(shù),例 10.23 求 a 和 b 中的大者. main ( ) int max( int, int) ; int a ,b, c ; scanf( “ %d ,%d ” , ,main ( ) int max( int, int) ; int a ,b, c ; int (*p)(int, int); scanf( “ %d ,%d ” , ,注意: int (*p)(int, int); 不能寫成 int (*p)( ); 否則導致 max 不能賦給 p, 因為二者 類型不一致,說明: 1. C語言中,函數(shù)調(diào)用可以有兩種形式.即 函數(shù)名調(diào)用和函數(shù)指針調(diào)用. 2. (*p ) ( ) 表示一個指向函數(shù)的指針變量,用于存放函數(shù)的入口地址. 若把某一個函數(shù)的入口地址賦給它,

溫馨提示

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

最新文檔

評論

0/150

提交評論