c程序設計上課課件第10講-指針_第1頁
c程序設計上課課件第10講-指針_第2頁
c程序設計上課課件第10講-指針_第3頁
c程序設計上課課件第10講-指針_第4頁
c程序設計上課課件第10講-指針_第5頁
已閱讀5頁,還剩140頁未讀, 繼續免費閱讀

下載本文檔

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

文檔簡介

1、廖雪峰第十講指針C語言程序設計 The C Programming Language溫州大學 甌江學院Copyright 2012, All rights reserved. 指 針本章要求理解指針的概念;掌握指針變量的定義和使用方法;掌握指針變量作函數參數時,數據的傳遞方式;掌握使用指針處理一維、二維數組的方法;掌握使用指針處理字符串的方法。 本章重點指針變量的定義和使用指針變量作函數參數使用指針處理一維數組和字符串本章難點使用指針處理一維、二維數組指 針地址與指針概述變量的指針與指向變量的指針變量指針運算符與指針變量運算數組與指針字符串與指針指向函數的指針返回指針值的函數指針數組與指向指針

2、的指針本章小結參考書目及網絡資源討論時間指 針地址與指針概述變量的指針與指向變量的指針變量指針運算符與指針變量運算數組與指針字符串與指針指向函數的指針返回指針值的函數指針數組與指向指針的指針本章小結參考書目及網絡資源討論時間地址與指針概述C語言的數據是以數據類型形式出現的,C的數據類型如下:地址與指針概述指針是C語言中廣泛使用的一種數據類型。運用指針編程是C語言最主要的風格之一。利用指針變量可以表示各種數據結構;能很方便地使用數組和字符串;并能象匯編語言一樣處理內存地址,從而編出精練而高效的程序。地址與指針概述(contd)地址的概念 程序是由CPU控制和運行的,在執行過程中需要處理各種數據,

3、這些數據被存放在內存中。 為了便于管理,內存空間被劃分成若干個大小相同(1個字節)的存儲單元,里面存放著各種數據。 內存中每一個存儲單元也有一個編號,這個編號被稱為地址。通過地址就可以十分方便地訪問指定的存儲單元。如果在程序中定義了一個變量,在對程序進行編譯時,系統就會給這個變量分配內存單元。變量的地址是存儲它的第1個單元的編號。 地址與指針概述(contd)地 址 2001 20022003 3000 內存單元的內容00100011 000111011100110000110011 CPUBUS指針指針嚴格地說,一個指針是一個地址,是一個常量。而一個指針變量卻可以被賦予不同的指針值,是變量。

4、但常把指針變量簡稱為指針。為了避免混淆,我們中約定:“指針”是指地址,是常量,“指針變量”是指取值為地址的變量。定義指針的目的是為了通過指針去訪問內存單元。變量的存儲與訪問直接訪問即系統直接根據變量的地址找到相應的存儲空間。間接訪問基本思想:將要訪問變量a的地址存放在另一個變量p中當需要訪問變量a時,先取出變量p的內容即變量a的地址再根據此地址找到變量a所對應的存儲空間。能夠存放其它變量地址的變量稱作指針變量。 直接訪問按變量地址存取變量值。假設程序已定義三個整型變量i、j、k,它們分別占用兩個字節。在程序中一般是通過變量名來對內存單元進行存取操作的。事實上,編譯后已經將變量名轉換為變量的地址

5、,對變量的存取都是通過地址進行的。變量名與地址之間的對應關系在編譯時確定的。int i, j, k;scanf(“%d”, &i);printf(“%d”, i);k=i+j間接訪問假設程序已定義了一個變量i_pointer,用來存放整型變量的地址,它被分配為3010、3011兩個字節。語句i_pointer=&i;將i的地址(2000)存放到i_pointer中。i_pointer的值就是2000,即變量i所占用單元的起始地址。存取變量i的值,先找到存放“i的地址”的變量i_pointer,從中取出i的地址(2000),然后到2000、2001字節取出i的值(3)。int i, *i_poi

6、nter;i_pointer=&i;地址與指針概述(contd)圖(a)表示直接訪問,根據變量i的地址直接對變量i的存儲單元進行存取訪問。圖(b)則表示間接訪問,先找到存放變量i地址的變量i_pointer,從其中得到變量i的地址,然后找到變量i的存儲單元,對它進行存取訪問。指針、指針變量 & 指針變量的值一個變量的地址稱為該變量的“指針”。例如,地址2000是變量i的指針。如果有一個變量專門用來存放另一變量的地址(即指針),則它稱為“指針變量”。如i_pointer就是一個指針變量。指針變量的值(即指針變量中存放的值)是地址(即指針)。為什么要為指針變量定義類型?既然指針變量的值是一個地址,

7、那么這個地址不僅可以是變量的地址,也可以是其它數據結構的地址。在一個指針變量中存放一個數組或一個函數的首地址有何意義呢? 因為數組或函數都是連續存放的。通過訪問指針變量取得了數組或函數的首地址,也就找到了該數組或函數。這樣一來,凡是出現數組,函數的地方都可以用一個指針變量來表示,只要該指針變量中賦予數組或函數的首地址即可。為什么要為指針變量定義類型?在C語言中,一種數據類型或數據結構往往都占有一組連續的內存單元。 用“地址”這個概念并不能很好地描述一種數據類型或數據結構,而“指針”雖然實際上也是一個地址,但它卻是一個數據結構的首地址,它是“指向”一個數據結構的,因而概念更為清楚,表示更為明確。

8、 這也是引入“指針”概念的一個重要原因。指 針地址與指針概述變量的指針與指向變量的指針變量指針運算符與指針變量運算數組與指針字符串與指針指向函數的指針返回指針值的函數指針數組與指向指針的指針本章小結參考書目及網絡資源討論時間變量的指針和指向變量的指針變量變量的指針就是變量的地址。存放變量地址的變量是指針變量。即在C語言中,允許用一個變量來存放指針,這種變量稱為指針變量。一個指針變量的值就是某個變量的地址或稱為某變量的指針。為了表示指針變量和它所指向的變量之間的關系,在程序中用“*”符號表示“指向”。變量的指針和指向變量的指針變量為了表示指針變量和它所指向的變量之間的關系,在程序中用“*”符號表

9、示“指向”。例如,i_pointer 代表指針變量,而*i_pointer 是i_pointer 所指向的變量。因此,下面兩個語句作用相同: i=3; *i_pointer=3; /*將3 賦給指針變量i_pointer所指向的變量。*/指針變量的定義格式 :基類型 *指針變量名 指針變量的命名規則與普通變量的命名規則相同。*表示所定義變量的類型為指針型。例如,int a;定義了一個整型變量a,而int *p;定義了一個指向整型變量的指針型變量p?;愋蜑镃語言的各種類型符。如int、float、char等。其含義為該指針變量中存放的是什么類型變量的地址。指針變量的定義下面都是合法的定義:fl

10、oat *pointer_3;/ pointer_3是指向float型變量的指針變量char *pointer_4;/pointer_4是指向字符型變量的指針變量可以用賦值語句使一個指針變量得到另一個變量的地址,從而使它指向一個該變量。如:pointer_1=&i;pointer_2 =&j;指針變量的定義指針變量前面的“*”,表示該變量的類型為指針型變量。例: float *pointer_1;指針變量名是pointer_1 ,而不是*pointer_1 。 在定義指針變量時必須指定基類型。指針變量的類型必須與所指向變量的地址的變量基類型一致。下面的賦值是錯誤的:float a; int *

11、pointer_1; pointer_1=&a; /錯誤。不能將float型變量的地址放到指向整型變量的指針變量中指針變量的引用指針變量的引用指針變量同普通變量一樣,使用之前不僅要定義說明,而且必須賦予具體的值。未經賦值的指針變量不能使用,否則將造成系統混亂,甚至死機。指針變量的賦值只能賦予地址, 決不能賦予任何其它數據,否則將引起錯誤。在C語言中,變量的地址是由編譯系統分配的,對用戶完全透明,用戶不知道變量的具體地址。兩個有關的運算符&和*&:取地址運算符。 *:指針運算符(或稱“間接訪問” 運算符)int a,*p1; /*定義一個整型變量a和一個指向整型變量的指針變量p1*/float

12、b,*p2; /*定義一個單精度型變量b和一個指向單精度型變量的指針變量p2*/p1=&a; /*使p1指向a,不能試圖通過p1=&b;使p1指向b*/p2=&b; /*使p2指向b,不能試圖通過p2=&a;使p2指向a */指針變量的訪問指針變量指向另一個變量所謂將指針變量指向另一個變量,就是將另一個變量的地址賦值給指針變量。只能將數據類型與指針變量基類型相同的變量的地址賦值給指針變量。 使用地址運算符&可以獲得指定變量的地址。引用指針變量 通過使用指針運算符*(或稱間接訪問運算符)可以間接訪問指針變量所指向的變量 格式: *指針變量通過指針變量間接訪問另一個變量#include main(

13、)int a=5,b=8,*p1,*p2; p1=&a;p2=&b;printf(a=%d,b=%dn,*p1,*p2);*p1=*p1+*p2; /*相當于a=a+b;*/printf(a+b=%dn,*p1); /*printf(a+b=%dn,a);*/通過指針變量訪問整型變量#include main()int a, b;int *pointer_1,*pointer_2;a=100;b=10;pointer_1=&a; /*把變量a的地址賦給pointer_1 */pointer_2=&b; /*把變量b的地址賦給pointer_2 */printf( %d, %dn,a,b);pr

14、intf( %d, %dn,*pointer_1,*pointer_2);return 0;“&”和“*”運算符使用說明如果已執行了語句pointer_1=&a;&*pointer_1的含義是什么?“&”和“*”兩個運算符的優先級別相同,但按自右而左方向結合,因此先進行*pointer_1的運算,它就是變量a,再執行&運算。因此,&*pointer_1與&a相同,即變量a的地址。如果已執行了語句pointer_1=&a; *&a的含義是什么?先進行&a運算,得a的地址,再進行*運算。即&a所指向的變量,即變量a。*&a和*pointer_1的作用是一樣的,它們都等價于變量a。即*&a與a等價。

15、“&”和“*”運算符使用說明若有pointer_1=&a; pointer_2=&*pointer_1;它的作用是將&a (a的地址)賦給pointer_2 ; 若pointer_2原來指向b,經過重新賦值后它已不再指向b了,而指向了a?!?”和“*”運算符使用說明如果已執行了語句pointer_1=&a;(*pointer_1)+相當于a+。注意括號是必要的。由于+和*為同一優先級別,且結合方向為自右而左。#include main()int a,b,c,*pointer_1;a=5;pointer_1=&a;b=(*pointer_1)+;printf(a=%d, %dn,a,*point

16、er_1);a=5;pointer_1=&a;c=*pointer_1+;printf(a=%d, %dn,a,*pointer_1);return 0;變量的指針和指向變量的指針變量按先大后小的順序輸出兩個整數a和b。#include 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(a=%d,b=%dn,a,b);printf(%d,%dn,*p1,*p2);return 0;兩個printf 函數作用是相同的, *p1 和*p2 就是變量a 和b。 “p1= &

17、a”和“p2=&b”不能寫成“*p1=&a”和 “*p2=&b”。變量的指針和指向變量的指針變量當輸入a=5,b=9時,由于ab,將p1和p2交換。交換前的情況見圖(a),交換后見圖(b)。變量的指針和指向變量的指針變量輸入a和b兩個整數,按先大后小的順序輸出a和b。#include main()void swap(int *p1,int *p2);int a,b;int*pointer_1,*pointer_2;scanf(%d,%d,&a,&b);pointer_1=&a;pointer_2=&b;if(ab) swap(pointer_1,pointer_2);printf(n%d,%d

18、n,a,b);void swap(int *p1,int *p2)int temp; temp=*p1;*p1=*p2;*p2=temp;實參pointer_1和pointer_2是指針變量,在函數調用時,將實參變量的值傳遞給形參變量。采取的依然是“值傳遞”方式。因此虛實結合后形參p1的值為&a,p2的值為&b。這時p1和pointer_1指向變量a,p2和pointer_2指向變量b。執行執行swap函數的函數體使*p1和*p2的值互換,也就是使a 和b 的值互換。函數調用結束后,p1和p2不復存在(已釋放)。指針變量作為函數參數當輸入a=5,b=9時,交換過程如圖所示。指針變量作為函數參數

19、不能通過改變指針形參的值而使指針實參的值改變。#include main()void swap(int *p1,int *p2);int a,b;int*pointer_1,*pointer_2;scanf(%d,%d,&a,&b);pointer_1=&a;pointer_2=&b;if(ab) swap(pointer_1,pointer_2);printf(n%d,%dn,a,b);void swap(int *p1,int *p2)int *temp; *temp=*p1;*p1=*p2;*p2=*temp;*p1就是a,是整型變量。而*temp是指針變量temp所指向的變量。但tem

20、p中并無確定的值(它的值是不可預見的),因此temp所指向的單元也是不可預見的。對*temp賦值有可能給一個存儲著重要數據的存儲單元賦值,將會破壞系統的正常工作狀況。應該將*p1的值賦給一個整型變量,如用整型變量temp作為臨時輔助變量實現*p1與*p2的交換。指針變量作為函數參數#include main()void swap(int *p1,int *p2);int a,b;int *pointer_1,*pointer_2;scanf(%d,%d,&a,&b);pointer_1=&a;pointer_2=&b;printf(n%d,%dn,*pointer_1,*pointer_2);

21、if(ab) swap(pointer_1,pointer_2);printf(n%d,%dn,*pointer_1,*pointer_2);printf(n%d,%dn,a,b);void swap(int *p1,int *p2)int temp; temp=*p1;*p1=*p2;*p2=temp;指針變量作為函數參數調用函數:swap(x, y); 被調用函數:swap(int *a, int *b)實參形參 x y 5 9 a b x y 5 9 a b 5 9 x y 5 9 swap(x,y)swap(a,b)調用前 調用時 調用后 a b 小結指針變量作形參時,對應實參為數據類

22、型與該指針變量基類型相同的變量的地址。指針變量作形參時,參數傳遞的形式仍然為值傳遞。調用函數時,形參與對應實參占據著不同的存儲空間,形參存儲空間中存放的是對應實參的地址。在函數調用過程中,通過對實參變量的間接訪問,改變了對應實參的值。當函數調用完畢后,形參的存儲空間仍然被收回,但此時實參存儲空間中已經保留了改變后的值,從而解決了在被調用函數中改變調用函數中變量的問題。 指 針地址與指針概述變量的指針與指向變量的指針變量指針運算符與指針變量運算數組與指針字符串與指針指向函數的指針返回指針值的函數指針數組與指向指針的指針本章小結參考書目及網絡資源討論時間指針運算符指針變量可以進行某些運算,但只能進

23、行賦值運算和部分算術運算及關系運算。取地址運算符&取地址運算符&是單目運算符,其結合性為自右至左,其功能是取變量的地址。取內容運算符*取內容運算符*是單目運算符,其結合性為自右至左,用來表示指針變量所指的變量。在*運算符之后跟的變量必須是指針變量。指針運算符指針運算符*和指針變量說明中的指針說明符*不是一回事。在指針變量說明中,“*”是類型說明符,表示其后的變量是指針類型。而表達式中出現的“*”則是一個運算符用以表示指針變量所指的變量。#include main()int a=5,*p;p=&a;/*表示指針變量p 取得了整型變量a的地址*/printf (%d,*p);/*表示輸出變量a 的

24、值*/指針變量運算賦值運算:指針變量的賦值運算有以下幾種形式。把一個變量的地址賦予指向相同數據類型的指針變量。例如:int a,*pa; pa=&a; /*把整型變量a 的地址賦予整型指針變量pa*/把一個指針變量的值賦予指向相同類型變量的另一個指針變量。如:int a,*pa=&a,*pb; pb=pa; /*把a 的地址賦予指針變量pb*/由于pa,pb 均為指向整型變量的指針變量,因此可以相互賦值。指針變量運算把數組的首地址賦予指向數組的指針變量。例如:int a5,*pa; pa=a;(數組名表示數組的首地址,故可賦予指向數組的指針變量pa)也可寫為:pa=&a0; /*數組第一個元素

25、的地址也是整個數組的首地址, 也可賦予pa*/ 當然也可采取初始化賦值的方法:int a5,*pa=a;把字符串的首地址賦予指向字符類型的指針變量。例如:char *pc; pc=C Language;或用初始化賦值的方法寫為:char *pc=C Language;這里應說明的是并不是把整個字符串裝入指針變量,而是把存放該字符串的字符數組的首地址裝入指針變量。指針變量運算把函數的入口地址賦予指向函數的指針變量。例如:int (*pf)(); pf=f; /*f為函數名*/加減算術運算對于指向數組的指針變量,可以加上或減去一個整數n。設pa 是指向數組a 的指針變量,則pa+n,pa-n, p

26、a+, +pa, pa-, -pa 運算都是合法的。指針變量加或減一個整數n 的意義是把指針指向的當前位置(指向某數組元素)向前或向后移動n個位置。數組指針變量向前或向后移動一個位置和地址加1 或減1 在概念上是不同的。因為數組可以有不同的類型,各種類型的數組元素所占的字節長度是不同的。加減算術運算如指針變量加1,即向后移動1 個位置表示指針變量指向下一個數據元素的首地址。而不是在原地址基礎上加1。int a5,*pa;pa=a; /*pa 指向數組a,也是指向a0*/pa=pa+2; /*pa 指向a2,即pa 的值為&a2*/指針變量的加減運算只能對數組指針變量進行,對指向其它類型變量的指

27、針變量作加減運算是毫無意義的。兩個指針變量之間的運算只有指向同一數組的兩個指針變量之間才能進行運算,否則運算毫無意義。兩指針變量相減:兩指針變量相減所得之差是兩個指針所指數組元素之間相差的元素個數。實際上是兩個指針值(地址)相減之差再除以該數組元素的長度(字節數)。例如: pf1和pf2 是指向同一浮點數組的兩個指針變量,設pf1 的值為2010H,pf2 的值為2000H,而浮點數組每個元素占4 個字節,所以pf1-pf2 的結果為(2010H-2000H)/4= 4,表示pf1 和 pf2之間相差4 個元素。兩個指針變量不能進行加法運算。如: pf1+pf2 是什么意思呢?毫無實際意義。兩

28、指針變量進行關系運算指向同一數組的兩指針變量進行關系運算可表示它們所指數組元素之間的關系。pf1=pf2 表示pf1 和pf2 指向同一數組元素;pf1pf2 表示pf1 處于高地址位置;pf1pf2 表示pf1 處于低地址位置。指針變量還可以與0 比較。設p為指針變量,則 p=0 表明p是空指針,它不指向任何變量; p!=0 表示p 不是空指針。兩指針變量進行關系運算空指針是由對指針變量賦予0 值而得到的。例如:#define NULL 0int *p=NULL;對指針變量賦0 值和不賦值是不同的。指針變量未賦值時,可以是任意值,是不能使用的。否則將造成意外錯誤。而指針變量賦0 值后,則可以

29、使用,只是它不指向具體的變量而已。指針運算符與指針變量運算(contd)#include main()int a=10,b=20,s,t,*pa,*pb; /*說明pa,pb 為整型指針變量*/pa=&a; /*給指針變量pa 賦值,pa 指向變量a*/pb=&b; /*給指針變量pb 賦值,pb 指向變量b*/s=*pa+*pb; /*求a+b 之和,(*pa 就是a,*pb 就是b)*/t=*pa*pb; /*本行是求a*b 之積*/printf(a=%dnb=%dna+b=%dna*b=%dn,a,b,a+b,a*b);printf(s=%dnt=%dn,s,t);指針運算符與指針變量運

30、算(contd)#include main()int a,b,c,*pmax,*pmin; /*pmax,pmin 為整型指針變量*/printf(“Input three numbers:n); /*輸入提示*/scanf(%d%d%d,&a,&b,&c); /*輸入三個數字*/*找出最大數和最小數*/if(ab) pmax=&a; /*指針變量賦值*/ pmin=&b; /*指針變量賦值*/ else pmax=&b; /*指針變量賦值*/ pmin=&a; /*指針變量賦值*/if(c*pmax) pmax=&c; /*判斷并賦值*/if(c*pmin) pmin=&c; /*判斷并賦值

31、*/printf(max=%dnmin=%dn,*pmax,*pmin); /*輸出結果*/指 針地址與指針概述變量的指針與指向變量的指針變量指針運算符與指針變量運算數組與指針字符串與指針指向函數的指針返回指針值的函數指針數組與指向指針的指針本章小結參考書目及網絡資源討論時間數組與指針數組指針和指向數組的指針變量一個變量有一個地址,一個數組包含若干元素,每個數組元素都在內存中占用存儲單元,它們都有相應的地址。所謂數組的指針是指數組的起始地址,數組元素的指針是數組元素的地址。指向數組元素的指針一個數組是由連續的一塊內存單元組成的。數組名就是這塊連續內存單元的首地址。一個數組也是由各個數組元素(下

32、標變量)組成的。每個數組元素按其類型不同占有幾個連續的內存單元。一個數組元素的首地址也是指它所占有的幾個內存單元的首地址。定義一個指向數組元素的指針變量int a10; /*定義a為包含10個整型數據的數組*/int *p; /*p為指向整型變量的指針*/下面是對指針變量賦值:p=&a0;把a0元素的地址賦給指針變量p。即p 指向a 數組的第0 號元素。p,a,&a0均指向同一單元,它們是數組a 的首地址,也是0 號元素a0的首地址。應該說明的是p 是變量,而a,&a0都是常量。數組與指針(contd)C語言規定,數組名代表數組的首地址,也就是第0 號元素的地址。因此,下面兩個語句等價:p=&

33、a0;p=a;在定義指針變量時可以賦給初值:int *p=&a0;它等效于:int *p; p=&a0;當然定義時也可以寫成: int *p=a;數組與指針(contd)數組指針變量說明的一般形式為:類型說明符 *指針變量名;其中類型說明符表示所指數組的類型。從一般形式可以看出指向數組的指針變量和指向普通變量的指針變量的說明是相同的。通過指針引用數組元素如果指針變量p已指向數組中的一個元素,則p+1指向同一數組中的下一個元素。引入指針變量后,就可以用兩種方法來訪問數組元素了。如果有int a5;且p的初值為&a0,則:p+i和a+i就是ai的地址,或者說它們指向a數組的第i個元素。 數組a a

34、0 a1 a2 a3 *(p+i) ai a9 p p+1, a+1 p+i, a+i p+9, a+9 通過指針引用數組元素*(p+i)或*(a+i)就是p+i 或a+i 所指向的數組元素,即ai。例如,*(p+5)或*(a+5)就是a5。指向數組的指針變量也可以帶下標,如pi與*(p+i)等價。 數組a a0 a1 a2 a3 *(p+i) ai a9 p p+1, a+1 p+i, a+i p+9, a+9 數組與指針(contd)引用一個數組元素可以用:下標法:用ai形式訪問數組元素。指針法:采用*(a+i)或*(p+i)形式,用間接訪問的方法來訪問數組元素,其中a是數組名,p是指向數

35、組的指針變量,其初值p=a。在計算數組元素ai的值時,C語言實際上先將其轉換為*(a+i)的形式,然后再進行求值,因此在程序中這兩種形式是等價的。如果對這兩種等價的表示形式分別施加地址運算符&,便可以看出:&ai和a+i的含義也是相同的。簡言之,一個通過數組下標實現的表達式可等價地通過指針和偏移量實現。數組與指針(contd)輸出數組中的全部元素。(下標法)include main()int i, a10;for(i=0;i10;i+) scanf(%d,&ai);printf(n);for(i=0;i10;i+) printf(%d ,ai);return 0;數組與指針(contd)輸出數

36、組中的全部元素。(通過數組名計算元素的地址,找出元素的值)#include main()int i, a10;for(i=0;i10;i+) scanf(%d,&ai);printf(n);for(i=0;i10;i+) printf(%d ,*(a+i);return 0;數組與指針(contd)輸出數組中全部元素。(用指針變量指向元素)#include main()int a10;int *p,i;for(i=0;i10;i+) scanf(%d,&ai);printf(n);for(p=a;p(a+10);p+) printf(%d ,*p);return 0;數組與指針(contd)輸

37、出數組中全部元素。(用指針變量指向元素)#include main()int a10=11,22,33,44,55,66,77,88,99,0, i;int *p;p=a;for(i=0;i10;) printf(a%d=%dn,i+,*p+);return 0;指針變量可以實現本身的值的改變。如p+是合法的;而a+是錯誤的。因為a是數組名,它是數組的首地址,是常量。數組與指針(contd)輸出數組中全部元素。(用指針變量指向元素)#include main()int *p,i,a10; p=a;for(i=0;i10;i+) *p+=i;for(i=0;i10;i+) printf(a%d=

38、%dn,i,*p+);要注意指針變量的當前值。從上例可以看出,雖然定義數組時指定它包含10個元素,但指針變量可以指到數組以后的內存單元,系統并不認為非法。數組與指針(contd)輸出數組中的全部元素。(用指針變量指向元素)#include main()int *p,i,a10;p=a;for(i=0;i10;i+) *p+=i;p=a;for(i=0;i10;i+) printf(a%d=%dn,i,*p+);*p+,由于+和*同優先級,結合方向自右而左,等價于*(p+)。*(p+)與*(+p)作用不同。若p 的初值為a,則*(p+)等價a0,*(+p)等價a1。(*p)+表示p所指向的元素值

39、加1。如果p當前指向a數組中的第i個元素,則: *(p-)相當于ai-;*(+p)相當于a+i;*(-p)相當于a-i。數組名作函數參數數組名可以作函數的實參和形參。如:main() int array10; f(array,10); f(int arr,int n); array為實參數組名,arr為形參數組名。數組名就是數組的首地址,實參向形參傳送數組名實際上就是傳送數組的地址,形參得到該地址后也指向同一數組。這就好象同一件物品有兩個彼此不同的名稱一樣。指針變量的值也是地址,數組指針變量的值即為數組的首地址,當然也可作為函數的參數使用。在編譯時是將arr按指針變量處理的,相當于將函數f的首

40、部寫成:f (int *arr, int n)數組與指針(contd)將數組a中n個整數按相反順序存放。將a0與an-1對換,再a1與an-2 對換,直到將a(n-1)/2與an-1-(int)(n-1)/2)對換。今用循環處理此問題,設兩個“位置指示變量”i和j,i的初值為0,j的初值為n-1。將ai與aj交換,然后使i的值加1,j的值減1,再將ai與aj交換,直到i=(n-1)/2為止,如圖所示。數組與指針(contd)將數組a中n個整數按相反順序存放。void inv(int x,int n) /*形參x是數組名*/ int temp, i, j, m=(n-1)/2;for(i=0;i

41、=m;i+) j=n-1-i;temp=xi; xi=xj;xj=temp; main()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 inverted array:n);for(i=0;i10;i+) printf(%d ,ai);數組與指針(contd)將數組a中n個整數按相反順序存放。/*形參x 為指針變量*/void inv(int *x,int n)int temp, *p, *i, *

42、j, m=(n-1)/2;i=x; j=x+n-1; p=x+m;for(;i=p;i+,j-) temp=*i;*i=*j;*j=temp; main()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 inverted array :n);for(i=0;i10;i+) printf(%d ,ai);數組與指針(contd)從10 個數中找出其中最大值和最小值。int max,min; /*全局變

43、量*/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 (*pmin)min=*p;main()int i,number10;printf(“Enter 10 integer umbers:n);for(i=0;i10;i+) scanf(%d,&numberi);max_min_value(number,10);printf(max=%d,min=%d,max,min);函數max_min_value

44、中的語句:max=min=*array; array是數組名,它接收從實參傳來的數組number 的首地址。*array相當于*(&array0)。上述語句與max=min=array0;等價。執行for循環時,p的初值為array+1,即p指向array1。以后每次執行p+,使p指向下一個元素。每次將*p和max與min比較。將大者放入max,小者放min。函數max_min_value 的形參array 可以改為指針變量類型。實參也可以不用數組名,而用指針變量傳遞地址。數組與指針(contd)實參也可以不用數組名,而用指針變量傳遞地址。int max,min; /*全局變量*/void m

45、ax_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 (*pmin) min=*p;main()int i,number10,*p;p=number; /*使p 指向number 數組*/printf(“Enter 10 integer umbers:n);for(i=0;i10;i+,p+) scanf(%d,p);p=number;max_min_value(p,10);printf(max=%d,min=%d

46、,max,min);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 (*pmin)min=*p;main()int i,number10;printf(“Enter 10 integer umbers:n);for(i=0;i10;i+) scanf(%d, &numberi );max_min_value(number,10);printf(max=%d

47、,min=%d,max,min);數組與指針(contd)歸納起來,如果有一個實參數組,想在函數中改變此數組中的元素的值,實參與形參的對應關系有:形參和實參都用數組名,如:main()int a10; f(a,10) f(int x,int n) 數組與指針(contd)實參用數組,形參用指針變量。實參a為數組名,形參x為指向整型變量的指針變量,函數執行時,x指向a0,即x=&a0,如下圖。通過改變x的值,從而可以指向a數組的任一元素。main()int a10;f(a,10) f(int *x, int n)數組與指針(contd)實參、形參都用指針變量。實參p和形參x都為指針變量。先使實參

48、指針變量p指向數組a,p的初值為&a0。然后,將p的值傳給形參指針變量x,x的初值也為&a0,如下圖。通過x值的改變可以使x指向數組a的任一元素。void main()int a10, *p=a; f(p, 10); void f(int *x, int n)數組與指針(contd)實參為指針變量,形參為數組名。實參p為指針變量,它指向a0。形參為數組名x,編譯系統把x作為指針變量處理,將a0的地址傳給形參x,使指針變量x指向a0。也可以理解為形參數組x和a數組共用同一段內存單元,如下圖。在函數執行過程中,使xi的值發生變化,而xi就是ai。這樣主函數就可以使用變化了的數組元素值。 void

49、main()int a10, *p=a; f(p,10); void f(int x, int n) 數組與指針(contd)將數組a中n個整數按相反順序存放(實參形參均用指針變量) 。#include void inv(int *x, int n)int temp, *p, *i, *j, m=(n-1)/2;i=x; j=x+n-1; p=x+m;for(;i=p;i+,j-) temp=*i;*i=*j;*j=temp; main()int i,a10=3,7,9,11,0,6,7,5,4,2, *p;printf(The original array:n);for(i=0;i10;i+

50、) printf(%d ,ai);printf(n); p=a; inv(a,10);printf(The inverted array :n);for(p=a;pa+10;p+) printf(%d ,*p);main函數中不能省去第一個“p=a”。因為,如果用指針變量作實參,必須先使指針變量有確定值,指向一個已定義的單元。能不能省去第二個“p=a”?為什么?指向多維數組的指針和指針變量二維數組指針變量說明的一般形式為:類型說明符 (*指針變量名)長度其中“類型說明符”為所指數組的數據類型。“*”表示其后的變量是指針類型?!伴L度”表示二維數組分解為多個一維數組時,一維數組的長度,也就是二維數

51、組的列數。應注意:“(*指針變量名)”兩邊的括號不可少,如缺少括號則表示是指針數組,意義就完全不同了。指向多維數組的指針和指針變量把二維數組a 分解為一維數組a0,a1,a2之后,設p為指向二維數組的指針變量??啥x為:int (*p)4它表示p是一個指針變量,它指向包含4個元素的一維數組。若指向第一個一維數組a0,其值等于a,a0,或&a00等。而p+i則指向一維數組ai。*(p+i)+j是二維數組i行j列的元素的地址,而*(*(p+i)+j)則是i 行j 列元素的值。多維數組的地址設有整型二維數組a23,設數組a的首地址為2000,各下標變量的首地址及其值如下圖。數組與指針(contd)用

52、指針變量輸出多維數組元素的值。#include main()int a34=0,1,2,3, 4,5,6,7, 8,9,10,11;int i, j, (*p)4;p=a;printf(%o,%o,%o,%on,p,a,a0,&a00);for(i=0;i3;i+) for(j=0;j4;j+) printf(%2d ,*(*(p+i)+j); printf(n);int (*p)4表示p是一個指針變量,它指向包含4個元素的一維數組。若指向第一個一維數組a0,其值等于a、a0 或&a00等。而p+i則指向一維數組ai。*(p+i)+j是二維數組i行j列的元素的地址,而*(*(p+i)+j)則是

53、i行j列元素的值。數組與指針(contd)用指針變量輸出二維數組元素的地址和值。#include void main()int a34=1,3,5,7, 9,11,13,15, 17,19,21,23;int *p;for(p=a0;pa0+12;p+) printf(addr=%o,p); printf(value=%2dn,*p); return 0; p是一個指向整型變量的指針變量,它可以指向一般的整型變量,也可以指向整型的數組元素。p的值是數組元素的地址,而*p是數組元素的值。數組與指針(contd)#include #define FMT %d,%dnvoid main()int a

54、34=1,2,3,4,5,6,7,8, 9,10,11,12;printf(FMT,a,*a);printf(FMT,a0,*(a+0);printf(FMT,&a0,&a00);printf(FMT,a1,(a+1);printf(FMT,&a10,*(a+1)+0);printf(FMT,a2,*(a+2);printf(FMT,&a2,a+2);printf(FMT,a10,*(*(a+1)+0);printf(FMT,*a2,*(*(a+2)+0);0行首地址和0行0列元素地址0行0列元素地址0行0首地址和0行0列元素地址1行0列元素地址和1行首地址1行0列元素地址2行0列元素地址2行

55、首地址1行0列元素的值2行0列元素的值數組與指針(contd)用指向數組的指針作函數參數一維數組名可以作為函數參數傳遞,多維數組也可以作函數參數傳遞。在用指針變量作形參以接受實參數組名傳遞來的地址時,有兩種方法:用指向變量的指針變量用指向一維數組的指針變量例:有一個班,3個學生,各學4門課,計算總平均分數以及第n個學生的成績。分析:可以使用指向數組的指針作函數參數而舉的例子。用函數average求總平均成績,用函數search找出并輸出第i個學生的成績。數組與指針(contd)#include void average(float *p,int n)float *p_end, sum=0;p_

56、end=p+n-1;for(;p=p_end;p+) sum=sum+(*p);printf(“Average=%5.2fn, sum/n);void search(float (*p)4,int i)int j; printf(“Scores of No.%d:n,i+1); for(j=0;j4;j+) printf(%5.2f ,*(*(p+i)+j);main()float score34=65,67,70,60, 80,87,90,81,90,99,100,98; average(*score,12); search(score,2);在函數average中形參p被聲明為指向浮點型變

57、量的指針變量,實參用*score,即score0,也就是&score00。將&score00的地址傳給p,使p指向score00。然后使p先后指二維數組的各個元素。函數search的形參則是指向包含4個元素的一維數組的指針變量。i為學生序號(0,1,2)。將實參score的值(代表該數組0行起始地址)傳給p,使p也指向score0。p+i是scorei的起始地址,*(p+i)+j是scoreij的地址,*(*(p+i)+j)是scoreij的值。數組與指針(contd)#include void search(float (*p)4,int n)int i,j,flag;for(j=0;jn;

58、j+) flag=0; for(i=0;i4;i+) if(*(*(p+j)+i)60) flag=1; if(flag=1) printf(No.%d fails:n,j+1); for(i=0;i4;i+) printf(%5.1f ,*(*(p+j)+i); printf(n);main()float score34=65,67,70,60, 80,87,90,81,90,99,100,98; search(score,3);實例是“查找有一門以上課程不及格的學生,并輸出他們全部的課程成績”。函數search的形參則是指向包含4個元素的一維數組的指針變量。將實參score的值(代表該數組

59、0行起始地址)傳給p,使p也指向score0。變量j代表學生的序號(0,1,2),i代表學生課程號。p+j是scorej的起始地址,*(p+j)+i是scoreji的地址,*(*(p+j)+i)是scoreji的值。數組與指針在C語言中,指針和數組之間的關系十分密切,通過數組下標所能完成的任何操作都可以通過指針來實現。雖然用指針實現的程序理解起來稍微困難一些,但一般來說,用指針編寫的程序比數組下標編寫的程序執行速度快?!癐n C, there is a strong relationship between pointers and arrays, Any operation that can

60、 be achieved by array subscripting can also be done with pointers. The pointer version will in general be faster but, at least to the uninitiated, somewhat harder to understand.” - Brian W. Kernighan and Dennis M. Ritchie. The C programming Language. 5.3 Pointers and Arrays.指 針地址與指針概述變量的指針與指向變量的指針變量

溫馨提示

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

評論

0/150

提交評論