c程序設(shè)計(jì)上課課件第10講-指針_第1頁
c程序設(shè)計(jì)上課課件第10講-指針_第2頁
c程序設(shè)計(jì)上課課件第10講-指針_第3頁
c程序設(shè)計(jì)上課課件第10講-指針_第4頁
c程序設(shè)計(jì)上課課件第10講-指針_第5頁
已閱讀5頁,還剩140頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

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

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

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

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

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

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

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

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

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

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

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

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

13、)int a=5,b=8,*p1,*p2; p1=&a;p2=&b;printf(a=%d,b=%dn,*p1,*p2);*p1=*p1+*p2; /*相當(dāng)于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;“&”和“*”運(yùn)算符使用說明如果已執(zhí)行了語句pointer_1=&a;&*pointer_1的含義是什么?“&”和“*”兩個(gè)運(yùn)算符的優(yōu)先級別相同,但按自右而左方向結(jié)合,因此先進(jìn)行*pointer_1的運(yùn)算,它就是變量a,再執(zhí)行&運(yùn)算。因此,&*pointer_1與&a相同,即變量a的地址。如果已執(zhí)行了語句pointer_1=&a; *&a的含義是什么?先進(jìn)行&a運(yùn)算,得a的地址,再進(jìn)行*運(yùn)算。即&a所指向的變量,即變量a。*&a和*pointer_1的作用是一樣的,它們都等價(jià)于變量a。即*&a與a等價(jià)。

15、“&”和“*”運(yùn)算符使用說明若有pointer_1=&a; pointer_2=&*pointer_1;它的作用是將&a (a的地址)賦給pointer_2 ; 若pointer_2原來指向b,經(jīng)過重新賦值后它已不再指向b了,而指向了a。“&”和“*”運(yùn)算符使用說明如果已執(zhí)行了語句pointer_1=&a;(*pointer_1)+相當(dāng)于a+。注意括號是必要的。由于+和*為同一優(yōu)先級別,且結(jié)合方向?yàn)樽杂叶蟆?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;變量的指針和指向變量的指針變量按先大后小的順序輸出兩個(gè)整數(shù)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;兩個(gè)printf 函數(shù)作用是相同的, *p1 和*p2 就是變量a 和b。 “p1= &

17、a”和“p2=&b”不能寫成“*p1=&a”和 “*p2=&b”。變量的指針和指向變量的指針變量當(dāng)輸入a=5,b=9時(shí),由于ab,將p1和p2交換。交換前的情況見圖(a),交換后見圖(b)。變量的指針和指向變量的指針變量輸入a和b兩個(gè)整數(shù),按先大后小的順序輸出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;實(shí)參pointer_1和pointer_2是指針變量,在函數(shù)調(diào)用時(shí),將實(shí)參變量的值傳遞給形參變量。采取的依然是“值傳遞”方式。因此虛實(shí)結(jié)合后形參p1的值為&a,p2的值為&b。這時(shí)p1和pointer_1指向變量a,p2和pointer_2指向變量b。執(zhí)行執(zhí)行swap函數(shù)的函數(shù)體使*p1和*p2的值互換,也就是使a 和b 的值互換。函數(shù)調(diào)用結(jié)束后,p1和p2不復(fù)存在(已釋放)。指針變量作為函數(shù)參數(shù)當(dāng)輸入a=5,b=9時(shí),交換過程如圖所示。指針變量作為函數(shù)參數(shù)

19、不能通過改變指針形參的值而使指針實(shí)參的值改變。#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中并無確定的值(它的值是不可預(yù)見的),因此temp所指向的單元也是不可預(yù)見的。對*temp賦值有可能給一個(gè)存儲著重要數(shù)據(jù)的存儲單元賦值,將會破壞系統(tǒng)的正常工作狀況。應(yīng)該將*p1的值賦給一個(gè)整型變量,如用整型變量temp作為臨時(shí)輔助變量實(shí)現(xiàn)*p1與*p2的交換。指針變量作為函數(shù)參數(shù)#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;指針變量作為函數(shù)參數(shù)調(diào)用函數(shù):swap(x, y); 被調(diào)用函數(shù):swap(int *a, int *b)實(shí)參形參 x y 5 9 a b x y 5 9 a b 5 9 x y 5 9 swap(x,y)swap(a,b)調(diào)用前 調(diào)用時(shí) 調(diào)用后 a b 小結(jié)指針變量作形參時(shí),對應(yīng)實(shí)參為數(shù)據(jù)類

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

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

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

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

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

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

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

29、使用,只是它不指向具體的變量而已。指針運(yùn)算符與指針變量運(yùn)算(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);指針運(yùn)算符與指針變量運(yùn)

30、算(contd)#include main()int a,b,c,*pmax,*pmin; /*pmax,pmin 為整型指針變量*/printf(“Input three numbers:n); /*輸入提示*/scanf(%d%d%d,&a,&b,&c); /*輸入三個(gè)數(shù)字*/*找出最大數(shù)和最小數(shù)*/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); /*輸出結(jié)果*/指 針地址與指針概述變量的指針與指向變量的指針變量指針運(yùn)算符與指針變量運(yùn)算數(shù)組與指針字符串與指針指向函數(shù)的指針返回指針值的函數(shù)指針數(shù)組與指向指針的指針本章小結(jié)參考書目及網(wǎng)絡(luò)資源討論時(shí)間數(shù)組與指針數(shù)組指針和指向數(shù)組的指針變量一個(gè)變量有一個(gè)地址,一個(gè)數(shù)組包含若干元素,每個(gè)數(shù)組元素都在內(nèi)存中占用存儲單元,它們都有相應(yīng)的地址。所謂數(shù)組的指針是指數(shù)組的起始地址,數(shù)組元素的指針是數(shù)組元素的地址。指向數(shù)組元素的指針一個(gè)數(shù)組是由連續(xù)的一塊內(nèi)存單元組成的。數(shù)組名就是這塊連續(xù)內(nèi)存單元的首地址。一個(gè)數(shù)組也是由各個(gè)數(shù)組元素(下

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

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

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

35、組的指針變量,其初值p=a。在計(jì)算數(shù)組元素ai的值時(shí),C語言實(shí)際上先將其轉(zhuǎn)換為*(a+i)的形式,然后再進(jìn)行求值,因此在程序中這兩種形式是等價(jià)的。如果對這兩種等價(jià)的表示形式分別施加地址運(yùn)算符&,便可以看出:&ai和a+i的含義也是相同的。簡言之,一個(gè)通過數(shù)組下標(biāo)實(shí)現(xiàn)的表達(dá)式可等價(jià)地通過指針和偏移量實(shí)現(xiàn)。數(shù)組與指針(contd)輸出數(shù)組中的全部元素。(下標(biāo)法)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;數(shù)組與指針(contd)輸出數(shù)

36、組中的全部元素。(通過數(shù)組名計(jì)算元素的地址,找出元素的值)#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;數(shù)組與指針(contd)輸出數(shù)組中全部元素。(用指針變量指向元素)#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;數(shù)組與指針(contd)輸

37、出數(shù)組中全部元素。(用指針變量指向元素)#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;指針變量可以實(shí)現(xiàn)本身的值的改變。如p+是合法的;而a+是錯誤的。因?yàn)閍是數(shù)組名,它是數(shù)組的首地址,是常量。數(shù)組與指針(contd)輸出數(shù)組中全部元素。(用指針變量指向元素)#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+);要注意指針變量的當(dāng)前值。從上例可以看出,雖然定義數(shù)組時(shí)指定它包含10個(gè)元素,但指針變量可以指到數(shù)組以后的內(nèi)存單元,系統(tǒng)并不認(rèn)為非法。數(shù)組與指針(contd)輸出數(shù)組中的全部元素。(用指針變量指向元素)#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+,由于+和*同優(yōu)先級,結(jié)合方向自右而左,等價(jià)于*(p+)。*(p+)與*(+p)作用不同。若p 的初值為a,則*(p+)等價(jià)a0,*(+p)等價(jià)a1。(*p)+表示p所指向的元素值

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

40、部寫成:f (int *arr, int n)數(shù)組與指針(contd)將數(shù)組a中n個(gè)整數(shù)按相反順序存放。將a0與an-1對換,再a1與an-2 對換,直到將a(n-1)/2與an-1-(int)(n-1)/2)對換。今用循環(huán)處理此問題,設(shè)兩個(gè)“位置指示變量”i和j,i的初值為0,j的初值為n-1。將ai與aj交換,然后使i的值加1,j的值減1,再將ai與aj交換,直到i=(n-1)/2為止,如圖所示。數(shù)組與指針(contd)將數(shù)組a中n個(gè)整數(shù)按相反順序存放。void inv(int x,int n) /*形參x是數(shù)組名*/ 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);數(shù)組與指針(contd)將數(shù)組a中n個(gè)整數(shù)按相反順序存放。/*形參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);數(shù)組與指針(contd)從10 個(gè)數(shù)中找出其中最大值和最小值。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);函數(shù)max_min_value

44、中的語句:max=min=*array; array是數(shù)組名,它接收從實(shí)參傳來的數(shù)組number 的首地址。*array相當(dāng)于*(&array0)。上述語句與max=min=array0;等價(jià)。執(zhí)行for循環(huán)時(shí),p的初值為array+1,即p指向array1。以后每次執(zhí)行p+,使p指向下一個(gè)元素。每次將*p和max與min比較。將大者放入max,小者放min。函數(shù)max_min_value 的形參array 可以改為指針變量類型。實(shí)參也可以不用數(shù)組名,而用指針變量傳遞地址。數(shù)組與指針(contd)實(shí)參也可以不用數(shù)組名,而用指針變量傳遞地址。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 數(shù)組*/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);數(shù)組與指針(contd)歸納起來,如果有一個(gè)實(shí)參數(shù)組,想在函數(shù)中改變此數(shù)組中的元素的值,實(shí)參與形參的對應(yīng)關(guān)系有:形參和實(shí)參都用數(shù)組名,如:main()int a10; f(a,10) f(int x,int n) 數(shù)組與指針(contd)實(shí)參用數(shù)組,形參用指針變量。實(shí)參a為數(shù)組名,形參x為指向整型變量的指針變量,函數(shù)執(zhí)行時(shí),x指向a0,即x=&a0,如下圖。通過改變x的值,從而可以指向a數(shù)組的任一元素。main()int a10;f(a,10) f(int *x, int n)數(shù)組與指針(contd)實(shí)參、形參都用指針變量。實(shí)參p和形參x都為指針變量。先使實(shí)參

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

49、main()int a10, *p=a; f(p,10); void f(int x, int n) 數(shù)組與指針(contd)將數(shù)組a中n個(gè)整數(shù)按相反順序存放(實(shí)參形參均用指針變量) 。#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函數(shù)中不能省去第一個(gè)“p=a”。因?yàn)?,如果用指針變量作?shí)參,必須先使指針變量有確定值,指向一個(gè)已定義的單元。能不能省去第二個(gè)“p=a”?為什么?指向多維數(shù)組的指針和指針變量二維數(shù)組指針變量說明的一般形式為:類型說明符 (*指針變量名)長度其中“類型說明符”為所指數(shù)組的數(shù)據(jù)類型?!?”表示其后的變量是指針類型?!伴L度”表示二維數(shù)組分解為多個(gè)一維數(shù)組時(shí),一維數(shù)組的長度,也就是二維數(shù)

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

52、指針變量輸出多維數(shù)組元素的值。#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是一個(gè)指針變量,它指向包含4個(gè)元素的一維數(shù)組。若指向第一個(gè)一維數(shù)組a0,其值等于a、a0 或&a00等。而p+i則指向一維數(shù)組ai。*(p+i)+j是二維數(shù)組i行j列的元素的地址,而*(*(p+i)+j)則是

53、i行j列元素的值。數(shù)組與指針(contd)用指針變量輸出二維數(shù)組元素的地址和值。#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是一個(gè)指向整型變量的指針變量,它可以指向一般的整型變量,也可以指向整型的數(shù)組元素。p的值是數(shù)組元素的地址,而*p是數(shù)組元素的值。數(shù)組與指針(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列元素的值數(shù)組與指針(contd)用指向數(shù)組的指針作函數(shù)參數(shù)一維數(shù)組名可以作為函數(shù)參數(shù)傳遞,多維數(shù)組也可以作函數(shù)參數(shù)傳遞。在用指針變量作形參以接受實(shí)參數(shù)組名傳遞來的地址時(shí),有兩種方法:用指向變量的指針變量用指向一維數(shù)組的指針變量例:有一個(gè)班,3個(gè)學(xué)生,各學(xué)4門課,計(jì)算總平均分?jǐn)?shù)以及第n個(gè)學(xué)生的成績。分析:可以使用指向數(shù)組的指針作函數(shù)參數(shù)而舉的例子。用函數(shù)average求總平均成績,用函數(shù)search找出并輸出第i個(gè)學(xué)生的成績。數(shù)組與指針(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);在函數(shù)average中形參p被聲明為指向浮點(diǎn)型變

57、量的指針變量,實(shí)參用*score,即score0,也就是&score00。將&score00的地址傳給p,使p指向score00。然后使p先后指二維數(shù)組的各個(gè)元素。函數(shù)search的形參則是指向包含4個(gè)元素的一維數(shù)組的指針變量。i為學(xué)生序號(0,1,2)。將實(shí)參score的值(代表該數(shù)組0行起始地址)傳給p,使p也指向score0。p+i是scorei的起始地址,*(p+i)+j是scoreij的地址,*(*(p+i)+j)是scoreij的值。數(shù)組與指針(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);實(shí)例是“查找有一門以上課程不及格的學(xué)生,并輸出他們?nèi)康恼n程成績”。函數(shù)search的形參則是指向包含4個(gè)元素的一維數(shù)組的指針變量。將實(shí)參score的值(代表該數(shù)組

59、0行起始地址)傳給p,使p也指向score0。變量j代表學(xué)生的序號(0,1,2),i代表學(xué)生課程號。p+j是scorej的起始地址,*(p+j)+i是scoreji的地址,*(*(p+j)+i)是scoreji的值。數(shù)組與指針在C語言中,指針和數(shù)組之間的關(guān)系十分密切,通過數(shù)組下標(biāo)所能完成的任何操作都可以通過指針來實(shí)現(xiàn)。雖然用指針實(shí)現(xiàn)的程序理解起來稍微困難一些,但一般來說,用指針編寫的程序比數(shù)組下標(biāo)編寫的程序執(zhí)行速度快?!癐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. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論