版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
1、程序設(shè)計基礎(chǔ)(C語言)東北大學(xué)高級語言程序設(shè)計課程組課程網(wǎng)站: 程序設(shè)計基礎(chǔ)(C語言)指針3n指針是語言的重要概念之一n它使語言比之其它程序設(shè)計語言更具特色n深入理解語言特性n指針是學(xué)習(xí)使用語言的難點(diǎn)n指針是C語言的一個重要概念n正確而靈活地使用指針n有效地描述各種復(fù)雜的數(shù)據(jù)結(jié)構(gòu)n動態(tài)地分配內(nèi)存空間n自由地在函數(shù)之間傳遞各種類型的數(shù)據(jù)n使程序簡潔、緊湊,執(zhí)行效率高n指針是C提供的一種數(shù)據(jù)結(jié)構(gòu)n屬于簡單數(shù)據(jù)類型n它的意義和作用明顯又不同于一般的數(shù)據(jù)類型概述4A直接直接BA間接間接1.預(yù)備知識n直接和間接的含義n內(nèi)存n即內(nèi)部存儲器,是由內(nèi)存單元組成n特點(diǎn)n存儲單元是線性連續(xù)的n存儲單元的最小單位為
2、字節(jié)51.預(yù)備知識n內(nèi)存n計算機(jī)的內(nèi)存中的每一個字節(jié)都有一個編號n所有的內(nèi)存單元都要統(tǒng)一進(jìn)行“編號”n這個編號就是該字節(jié)在整個內(nèi)存中的“地址”n所有的內(nèi)存單元都要有地址n每一內(nèi)存單元具有唯一的內(nèi)存地址n系統(tǒng)為每一個已定義的變量分配一定存儲空間n使變量名與內(nèi)存的一個地址相對應(yīng)n通過地址我們就能夠訪問該地址所標(biāo)識的存儲單元n程序處理過程n需要根據(jù)地址取出變量所對應(yīng)的內(nèi)存單元中存放的值n參與計算/操作n處理結(jié)果存入相應(yīng)的變量名所對應(yīng)的內(nèi)存單元 0 1 2 3 2000 0 1 2 3 2000地址地址4545變量內(nèi)容變量內(nèi)容61.預(yù)備知識n計算機(jī)的尋址方式n直接尋址n間接尋址存入存入/ /取出取出
3、數(shù)據(jù)數(shù)據(jù) 數(shù)據(jù)數(shù)據(jù)內(nèi)存內(nèi)存地址地址 1003 1004 1008 100C 1003 1004 1008 100C 存入存入/ /取出取出B B單元單元內(nèi)存內(nèi)存地址地址 1050 1051 3020 3021 1050 1051 3020 3021 地地 址址數(shù)據(jù)數(shù)據(jù) 數(shù)據(jù)數(shù)據(jù)A A單元單元71.預(yù)備知識nC語言如何處理?n高級語言中的變量具有三個屬性n變量的名、變量的值、變量的地址n編程者使用c程序的一個變量n定義變量的數(shù)據(jù)類型n數(shù)據(jù)類型決定了一個變量在內(nèi)存中所占用的存儲空間的大小n變量在內(nèi)存中總是占用幾個連續(xù)的字節(jié)n定義變量名n語言的編譯系統(tǒng)會根據(jù)變量的數(shù)據(jù)類型為該變量分配內(nèi)存單元n確定變
4、量的地址n變量的地址就是為變量分配的內(nèi)存單元的起始編號n就可以通過變量名對內(nèi)存中變量對應(yīng)的地址進(jìn)行操作81.預(yù)備知識2000200020022002200120012003200320042004200520052006200620072007地址地址變量名變量名 變量類型變量類型 字節(jié)數(shù)字節(jié)數(shù) i int 2 i int 21010a3.14159263.1415926pi float 4 pi float 4 ch char 1 ch char 191.預(yù)備知識nC語言如何處理?n直接訪問n通過變量名訪問數(shù)據(jù)的方式稱為直接訪問 n例如:printf(%d, n); /* 通過變量名訪問變量
5、n */ n間接訪問n如果將變量n的地址存放在另一個變量pn中,通過訪問變量pn,間接達(dá)到訪問變量i的目的,這種方式稱為變量的間接訪問 n在C語言中,間接尋址方式訪問內(nèi)存是通過指針變量實現(xiàn)的n指針變量通過直接尋址方式訪問獲得的是一個地址值n在該地址起始的一個存儲單元中存放程序需要的數(shù)據(jù)1010101020022002200420041010101030030010121012102.指針變量n定義n用于指向其他變量的變量 n指針變量是一個變量n和普通變量一樣占用一定的存儲空間n該存儲空間存放的是一個地址值而不是普通的數(shù)據(jù)值n指針變量是一個地址變量n指針變量的值是一個內(nèi)存單元的地址n它指向另一個
6、變量的值n指針就是地址n當(dāng)將變量的地址存入指針變量后,就說這個指針指向了該變量n指針變量只能存放某一數(shù)據(jù)類型的變量n問題?n變量的類型和指向變量的類型之間的區(qū)別?112.指針變量n指針變量的聲明n指針變量與一般的變量的區(qū)別n格式 *指針變量名;n說明n數(shù)據(jù)類型表示指針?biāo)赶虻臄?shù)據(jù)的數(shù)據(jù)類型n提示:不是指針變量的數(shù)據(jù)類型n*是指針的標(biāo)志,表示它后面的變量名是指針類型n例nint *i_p;/*定義了指針變量i_p ,指向的對象類型為整型*/n char *cp;/*定義了指針變量cp, 指向的對象類型為字符型*/122.指針變量n指針變量的聲明n提示n聲明語句的*只能用于指針變量n這種表示方式說
7、明被聲明的變量是一個指針n*不針對聲明語句中的所有變量n每一個指針都必須在其名字前面有一個前綴*聲明n例如:int *pt1,pt2;npt2為整型變量而不是整型指針變量n指針變量名是pt1而不是*pt1n指針變量只能指向定義時規(guī)定的類型變量n只有同一數(shù)據(jù)類型的地 址才能存放在指向該類型變量的指針變量中n例如: int *ip;/*ip指針變量只能存放整型變量的地址*/132.指針變量n指針變量的聲明n提示n在定義指針時可以用void將指針定義為空類型n不指定指針指向一個確定的類型n區(qū)分“值”與“內(nèi)容”的含義n例如n整型變量是內(nèi)容為整型數(shù)值的變量n整型指針變量是存放整型變量地址的變量n在引用指
8、針變量前必須首先讓指針指向一個變量n這一點(diǎn)非常重要n定義指針變量后,并未確定該變量指向何處,該變量的值是不確定的指針指針P P指針變量指針變量p p的地址的地址內(nèi)存單元內(nèi)存單元142.指針變量n指針變量初始化n在使用指針變量時,要首先對指針變量進(jìn)行初始化,讓指針變量指向一個具體的變量n初始化的方式n使用賦值語句n例nint i, *pi; /* 說明指針變量pa和變量a */pi=&i; /*使用取地址符&把變量i的地址賦值給指針變量:pi指向了整型變量i */ n說明指針變量的時候同時進(jìn)行n例:使用先聲明變量的地址nint i,*pi=&i;n問題?n寫成int *p
9、a; *pa=&a;會出現(xiàn)什么問題? 152.指針變量n指針變量初始化n在使用指針變量時,要首先對指針變量進(jìn)行初始化,讓指針變量指向一個具體的變量n初始化的方式n給指針變量賦空值(賦值為符號常量NULL )n例np=NULL;/*表示指針p為空,沒有指向任何對象*/ n一般情況下給沒有初始值的指針變量賦值為NULLn實際上,NULL是整數(shù)0,系統(tǒng)保證0單元不存儲任何數(shù)據(jù)的值(地址)n NULL是頭文件以及其它幾個頭文件中定義的符號常量指針指針P P空地址空地址NULLNULL指針變量指針變量內(nèi)存單元內(nèi)存單元162.指針變量n指針變量初始化n提示n在使用指針之前一定要對其進(jìn)行初始化n否則
10、程序不知道指向何處n系統(tǒng)在執(zhí)行程序時會給出如下的信息nrun-time error R6001null pointer assigmentn或者引起更嚴(yán)重的錯誤系統(tǒng)崩潰n對未使用的指針應(yīng)該賦以空值NULLn表明它未指向任何地方n這并不是對指針的初始化n只是 表示該指針未被使用而已172.指針變量n指針變量初始化n提示n一個指針變量賦空值與不賦值是完全不同的概念n前者是有不指向任何變量的地址n后者是一個不確定的隨機(jī)值n這時指針可能指向一個事先未指定的數(shù)據(jù)n利用空指針可以簡化程序代碼、提高效率n指針變量應(yīng)具有無符號整型類型的值n存放的是地址n由于地址本身的特征,不能將一個整型值賦給一個指針變量。同
11、樣也不能將指針變量的值賦給一個整型變量n 例如:int *p;p=2000;(非法)182.指針變量n指針變量初始化n提示n用void將指針定義為空類型n即不指定指針指向一個確定的類型n例如:void *p;/*表示指針變量P不指向一個確定的類型*/ n它的作用僅用來存放一個地址n作用n任何類型的指針都可以賦給指向void類型的指針n指向void類型的指針也可以賦給任何類型的指針n但是:不能復(fù)引用void*類型的指針n編譯器不能根據(jù)類型確定它引用的字節(jié)數(shù)n常見錯誤n將一種類型的指針賦給另一種類型的指針,而這兩種指針都不是void*類型【例】定義指針變量【例】定義指針變量 void void *
12、 *p2p2; int int * *p1p1,i=5i=5; p1=&i p1=&i;p2=p1p2=p1; 演示演示9191。C C 193.指針變量n指針變量的運(yùn)算n語言提供的指針運(yùn)算n取地址運(yùn)算(&)n作用是取變量的地址n運(yùn)算對象必須是(任意類型的)變量n例如n&i /*表示求變量 i的地址*/nint x=3, *p;p=&x /* &表示取的地址,將變量地址賦給指針變量p */n提示n&是一個單目運(yùn)算符,它返回變量的地址n&的操作數(shù)必須是一個變量n取地址運(yùn)算符“&”是取操作對象的地址而不是其值203.指針變量n
13、指針變量的運(yùn)算n語言提供的指針運(yùn)算n取內(nèi)容運(yùn)算(*)n運(yùn)算對象必須是指針(該指針?biāo)赶虻膶ο罂梢允侨我忸愋停﹏作用是取指針?biāo)赶蜃兞康膬?nèi)容。*也稱為“間接引用運(yùn)算符”或“指針的復(fù)引用”n 例如na=*prt; /*表示指針 prt所指向變量的內(nèi)容賦a*/ nint a=3, *p, x;pa=&a;nx=*pa; /* *pa表示取指針變量pa所指單元的內(nèi)容,即變量a的值,則x=3 */ 213.指針變量n指針變量的引用n當(dāng)指針變量定義和賦值之后,引用變量的方式n用變量名直接引用n例如nscanf(“%d”,&a);/*在函數(shù)中直接使用變量a的地址 */n通過指向變量的指針間接
14、引用n利用指針變量,提供對變量的一種“間接訪問”形式n指針變量的引用形式 *指針變量 n含義是指針變量所指向的值n例如nint a=3,*pa;pa=&a; /* 指針pa指向變量a*/printf(%dn,*pa); /* 通過 * 運(yùn)算符實現(xiàn)間接訪問 */223.指針變量n指針變量的引用n例:用指針變量進(jìn)行輸入輸出 main main()() int int * *p p,m m; scanf scanf(“%d”“%d”,&m&m);); p=&m p=&m; printf printf(“%d”“%d”,* *p p);); main main(
15、)() int int * *p p,m m; p=&m p=&m; scanf scanf(“%d”“%d”, p p );); printf printf(“%d”“%d”, m m );); 運(yùn)行結(jié)果完全一樣。請思考一下若將程序修改為如下形式:運(yùn)行結(jié)果完全一樣。請思考一下若將程序修改為如下形式:mainmain()() int int * *p p,m m; scanf scanf(“%d”“%d”, p p );); p=&m p=&m; printf printf(“%d”“%d”, m m );); 會產(chǎn)生什么結(jié)果?會產(chǎn)生什么結(jié)果?23#includ
16、e#includemain()main() int a, int a, * *aptr;aptr; a=7; a=7; aptr=&a; aptr=&a; printf(“The address of a is %pn” printf(“The address of a is %pn” ”The value of aptr is %pnn”,&a,aptr); ”The value of aptr is %pnn”,&a,aptr); printf(“The value of a is %dn” printf(“The value of a is %dn” ”T
17、he value of ”The value of * *aptr is %dnn”,a,aptr is %dnn”,a,* *aptr);aptr); printf(“Proving that printf(“Proving that * * and & are complements of” and & are complements of” ”each other .n& ”each other .n&* *aptr=%pnaptr=%pn* *&aptr=%pn”, &aptr=%pn”, &* *aptr,aptr,* *&am
18、p;aptr);&aptr); 3.指針變量n指針變量的引用n例:本程序演示了指針運(yùn)算符的用法24【例】【例】 main main()() int int * *p1p1,* *p2p2; int i=10 int i=10,j=20j=20; p1=&i p1=&i; p2=&j p2=&j; p2=p1 p2=p1; printf printf(“* *p1=%dp1=%d;* *p2=%dn” p2=%dn” ,* *p1p1,* *p2p2);); printf printf(“i=%d“i=%d;j=%dn” j=%dn” ,i i,j j);
19、); printf printf(“p1=%p“p1=%p,p2=%pn”p2=%pn”,p1p1,p2p2);); 本題中若本題中若* *p2=p2=* *p1p1?將將p1p1指向變量的值傳遞給指向變量的值傳遞給* * p2 p2的內(nèi)的內(nèi)存單元。即存單元。即j j的內(nèi)存單元中,的內(nèi)存單元中,P2P2和和p1p1中存放的地址并不發(fā)生變化。中存放的地址并不發(fā)生變化。結(jié)果為:結(jié)果為: * *p1=10p1=10;* *p2=10p2=10 i=10 i=10;j=20j=20結(jié)果:結(jié)果: * *p1=10p1=10;* *p2=10p2=10 i=10 i=10;j=10j=103.指針變量25
20、3.指針變量n指針變量的提示n取內(nèi)容運(yùn)算符*p與定義指針變量時使用的*p含義不同n定義時的*p表示的是一個指針變量,該變量指向一個整型變量的地址n取內(nèi)容運(yùn)算符*p則表示取指針變量的內(nèi)容,即另一個變量值n對指針的引用需要*和&n&用于求任一類型變量的指針,求出的指針具有對應(yīng)的類型n*和指針一起使用時被認(rèn)為是同類型的一個變量n可以參與該類型變量的一切運(yùn)算n*和&是一對功能恰好相反的運(yùn)算操作符n在實際應(yīng)用中, 應(yīng)特別注意&和*的操作對象n&的操作對象是一個“變量”n*的操作對象是一個“地址”264.指針與數(shù)組n指針和數(shù)組緊密聯(lián)系n對數(shù)組元素的訪問可以通過指針和
21、借助數(shù)組元素下標(biāo)的方法實現(xiàn)n凡是由數(shù)組下標(biāo)完成的操作皆可用指針來實現(xiàn)n“下標(biāo)方式“訪問數(shù)組元素n通過數(shù)組的下標(biāo)唯一確定了某個數(shù)組元素在數(shù)組中的順序和存儲地址n例如:int a5 = 1, 2, 3, 4, 5, x x=a0; /* 通過下標(biāo)將第1個元素的值賦給x=1 */ 274.指針與數(shù)組n指針和數(shù)組緊密聯(lián)系n對數(shù)組元素的訪問可以通過指針和借助數(shù)組元素下標(biāo)的方法實現(xiàn)n凡是由數(shù)組下標(biāo)完成的操作皆可用指針來實現(xiàn)n指針最常見的一種用途就是指向數(shù)組元素n當(dāng)一個指針指向數(shù)組后,就可以靈活快速地處理數(shù)組元素,從而體現(xiàn)出指針的優(yōu)點(diǎn)n“指針方式”訪問數(shù)組中的元素n一個數(shù)組(/數(shù)組元素)有相應(yīng)的地址,可以將
22、數(shù)組的起始地址或某一個數(shù)組元素的地址放到一個指針變量中n數(shù)組的指針就是數(shù)組的起始地址(數(shù)組名),既數(shù)組第一個元素的地址(&數(shù)組名0)n數(shù)組元素的指針就是該數(shù)組元素的地址284.指針與數(shù)組n指針和數(shù)組緊密聯(lián)系n分析程序n語言中規(guī)定n數(shù)組第1個(下標(biāo)為0)元素的地址就是數(shù)組的首地址n數(shù)組名代表的就是數(shù)組的首地址n數(shù)組名代表的一個地址常量,是數(shù)組的首地址n它不同于指針變量#include main ( ) int a = 1, 2, 3, 4, 5 ; int x, y, *pt,*p2; pt = &a0; x = *(pt+2); p2=&a4; y=pt4; print
23、f (*p=%d, x=%d, y=%dn, *pt, x,y,*p2); 294.指針與數(shù)組n指針和數(shù)組緊密聯(lián)系n語言中規(guī)定說明n當(dāng)指針指向數(shù)組首地址時(pt=ary或pt=&ary0時) 指針可以向數(shù)組一樣使用n提示n對數(shù)組元素的訪問,下標(biāo)方式和指針方式是等價的n從語言系統(tǒng)內(nèi)部處理機(jī)制上講,指針方式效率高n指針方式不如下標(biāo)方式直觀n下標(biāo)方式可以直截了當(dāng)?shù)乜闯鲆L問的是數(shù)組中的哪個元素n指向數(shù)組的指針變量,進(jìn)行運(yùn)算以后,指針變量的值改變了,其當(dāng)前指向的是哪一個數(shù)組元素不再是一目了然* *(pt+2pt+2)pt2pt2 ary2 ary2 * *(ary+2ary+2)304.指針與
24、數(shù)組n指針和數(shù)組的可替代性nC語言中的指針和數(shù)組幾乎可以互換n指針可以用來完成涉及數(shù)組下標(biāo)的操作n例如:int a10;int *p;n若p=&a0;或 p=a;則p就指向了數(shù)組a的首址n當(dāng)p指向了一維數(shù)組a,指針對數(shù)組元素可以表示:np+n與a+n( n (偏移量)的取值為09 )表示數(shù)組元素 an的地址,既&an n*(p+n)和*(a+n) 表示數(shù)組元素an ( n的取值為09 ) n指向數(shù)組的指針變量也可以用數(shù)組的下標(biāo)形式pn,其效果相當(dāng)于*(p+n),等價于an314.指針與數(shù)組n指針和數(shù)組的可替代性n例#include void strcopy1(char str,
25、const char *); void strcopy2(char str,const char *); main( ) char str110,*str2=“teacher”; char str310,*str4=“boys and girls”; strcopy1 (str1,str2); printf(“str1=%sn”,str1); strcopy2(str3,str4); printf(“str3=%sn”,str3); 這兩個函數(shù)都將一這兩個函數(shù)都將一個字符串(可能是個字符串(可能是一個字符數(shù)組)拷一個字符數(shù)組)拷貝到一個字符數(shù)組貝到一個字符數(shù)組中,比較這兩個函中,比較這兩個函數(shù)
26、原型可以發(fā)現(xiàn)其數(shù)原型可以發(fā)現(xiàn)其形式是相同的,雖形式是相同的,雖然這兩個函數(shù)完成然這兩個函數(shù)完成同樣的功能,但是同樣的功能,但是他們的實現(xiàn)過程是他們的實現(xiàn)過程是不同的。不同的。32/* 采用數(shù)組表示法將采用數(shù)組表示法將s2拷貝到拷貝到s1.*/void strcopy1(char *s1,const char *s2) int i; for(i=0;s1i=s2i;i+) ; /*函數(shù)體中沒有任何動作函數(shù)體中沒有任何動作*/ /* 采用指針表示法將采用指針表示法將s2拷貝到拷貝到s1.*/ void strcopy2(char *s1,const char *s2) for( ;*s1=*s2;
27、s1+,s2+) ; /*函數(shù)體中沒有任何動作函數(shù)體中沒有任何動作*/ 4.指針與數(shù)組334.指針與數(shù)組n指針和數(shù)組的可替代性n數(shù)組的表示法n數(shù)組/下標(biāo)n指針/偏移量n利用*p、*(p+1)、來代表數(shù)組a0、a1n數(shù)組/偏移量n對數(shù)組的引用以*a、*(a+ 1)、代替a0、a9n n指針/下標(biāo)n表達(dá)式p1引用了數(shù)組元素a134【例【例1 1 】采用指針】采用指針/ /偏移量表示的地址法輸入輸出數(shù)組元素。偏移量表示的地址法輸入輸出數(shù)組元素。mainmain()() int n,a10, int n,a10,* *pa=a; /pa=a; /* *定義時對指針變量初始化定義時對指針變量初始化* *
28、/ / for (n=0;n=9;n+) for (n=0;n=9;n+) scanf scanf(“%d”,pa+n“%d”,pa+n); ; for for(n=0;n=9;n+n=0;n=9;n+) printf printf(“%d”,“%d”,* *(pa+npa+n); ; printf printf(“n”“n”); ; 【例【例2 2】采用表示的數(shù)組】采用表示的數(shù)組/ /偏移量表示的地址法輸入輸出數(shù)組元素。偏移量表示的地址法輸入輸出數(shù)組元素。 main main()() int n,a10, int n,a10,* *pa=a; /pa=a; /* *定義時對指針變量初始化定義
29、時對指針變量初始化* */ / for (n=0;n=9;n+) for (n=0;n=9;n+) scanf scanf(“%d”,a+n“%d”,a+n); ; for for(n=0;n=9;n+n=0;n=9;n+) printf printf(“%d”,“%d”,* *(a+na+n); ; printf printf(“n”“n”); ; 4.指針與數(shù)組35【例【例3 3】采用指針】采用指針/ /下標(biāo)法輸入輸出數(shù)組元素。下標(biāo)法輸入輸出數(shù)組元素。 main main()() int n,a10, int n,a10,* *pa=a;pa=a; for (n=0;n=9;n+) for
30、 (n=0;n=9;n+) scanf scanf(“%d”,&pan“%d”,&pan); ; for for(n=0;n=9;n+n=0;n=9;n+) printf printf(“%d”,pan“%d”,pan); ; printf printf(“n”“n”); ; 【例【例4 4】采用數(shù)組】采用數(shù)組/ /下標(biāo)法輸入輸出數(shù)組元素。下標(biāo)法輸入輸出數(shù)組元素。 main main()() int n,a10; int n,a10; for (n=0;n=9;n+) for (n=0;n=9;n+) scanf scanf(“%d”,&an“%d”,&an);
31、 ; for for(n=0;n=9;n+n=0;n=9;n+) printf printf(“%d”,an“%d”,an); ; printf printf(“n”“n”); ; 4.指針與數(shù)組36mainmain()()int ary4=int ary4=2,4,8,162,4,8,16; int int * *iprtiprt,i i; iprt=ary iprt=ary; / /* *按正序輸出數(shù)組元素按正序輸出數(shù)組元素* */ / for for (i=0i=0;i4i=0i=0;i- -i- -) printf printf(“%d” “%d” ,* *( iprt+i iprt+
32、i );); prntf prntf(“n”“n”);); 4.指針與數(shù)組n指針和數(shù)組的可替代性n例:將一個數(shù)組按正向、逆向輸出374.指針與數(shù)組n指針和數(shù)組的關(guān)系n提示n指針變量與數(shù)組的區(qū)別n指針變量是地址變量,數(shù)組名是地址常量n指針變量的內(nèi)容可以在程序運(yùn)行過程中被修改,數(shù)組名一旦被聲明,它的值在整個程序運(yùn)行中是不能改變n(p+1)和 *(a+ 1)都可以表示數(shù)組元素a1, 兩者并不能完全等價n對 數(shù)組a只能引用,不能修改n實際上就是指針與指針變量的區(qū)別n對于數(shù)組名,雖然可以使用它得到其元素的值,但它僅表示數(shù)組的首地址,不能將其改變n試圖用指針?biāo)阈g(shù)運(yùn)算修改數(shù)組名是一種語法錯誤384.指針與數(shù)
33、組n指針和數(shù)組的關(guān)系n提示n指針變量與數(shù)組的區(qū)別n指針變量可以改變其自身的值,應(yīng)該特別注意其的當(dāng)前值n 例如:對上例程序中的a和pa,若有程序段:n pa=a;printf(”%dn”,*pa);n pa+;printf(“%dn”,*pa);n第一個printf輸出的是a0的值n第二個printf則輸出的是a1的值n指向數(shù)組的指針在數(shù)組處理時不要越界n由于C語言不檢查數(shù)組越界,對一個僅有10個元素的數(shù)組a引用第11個元素a10時系統(tǒng)仍按 *(a+10)處理,發(fā)生錯誤394.指針與數(shù)組n指針的運(yùn)算n指針的運(yùn)算旨在針對數(shù)組進(jìn)行n指針的運(yùn)算n指針與正整數(shù)的加減運(yùn)算n兩個指針的減法運(yùn)算n兩個指針的關(guān)
34、系運(yùn)算n禁止的運(yùn)算n指針做乘除法運(yùn)算n指針進(jìn)行位操作運(yùn)算n指針與浮點(diǎn)型數(shù)據(jù)運(yùn)算n兩個指針相加沒有意義n指針運(yùn)算的結(jié)果依賴于指針?biāo)赶驅(qū)ο蟮拇笮指向?qū)ο蟮臄?shù)據(jù)類型404.指針與數(shù)組n指針的運(yùn)算n指針與正整數(shù)的加減運(yùn)算n該指針下移或上移整型值所指定個數(shù)的存儲單元的內(nèi)存地址n存儲單元的大小就是該指針的數(shù)據(jù)類型所需要的內(nèi)存的大小np+(-)i*sizeof(type)n對指針的加/減(整數(shù))操作運(yùn)算在用指針訪問數(shù)組元素是經(jīng)常用到n表達(dá)式:p+n表示指針p所指向當(dāng)前元素之后的第n個元素n而表達(dá)式:p-n表示指針p所指向當(dāng)前元素之前的第n個元素指針變量指針變量ptr內(nèi)存內(nèi)存地址地址20002001200
35、2200320042005200620072008414.指針與數(shù)組n指針的運(yùn)算n指針與正整數(shù)的加減運(yùn)算n例如: int a10 ,*p; n p=a;(或p=&a0 ;)p+ip+i a10 a10 a0 a0 a1 a1 ai ai a9 a9p pp-ip-i a10 a10 a0 a0 a1 a1 ai ai a9 a9200020022004200+2*i2018p p4.指針與數(shù)組n指針的運(yùn)算n指針與正整數(shù)的加減運(yùn)算n自增/自減n指針的自增(+)/自減(-)運(yùn)算分別表示將指針移動到下一個/上一個存儲單元并指向新的數(shù)據(jù)np+的含義n指針加,指向數(shù)組中的下一個元素np-的含義n
36、指針減,指向數(shù)組中的前一個元素main()int *prt; int arrary=2,4,6,8,10; prt=array; prt+=3; prt-; prt-=2; prt+; 96。C array5 array5 array0 array0 array1 array1 array2 array2 array3 array3 array4 array42 24 46 68 810102000200020022002200420042006200620082008arrayarrayprtprt(1)(1)(3)(3)(5 5)(2)(2)434.指針與數(shù)組n指針的運(yùn)算n提示n例如:in
37、t a5,*pa:pa=a;npa+; /*使pa指向下一個元素a1;*/n*pa; /*指針?biāo)赶虻臄?shù)組名(或變量或數(shù)組元素)*/n*pa+; /*先取出pa所指向元素的值 (*pa),后pa+1送 n 與pa。由于+與*的優(yōu)先級相同,自右向左的結(jié) n 合方向,所以它等價于*(pa+);*/n*(+pa);/*先令pa加1,再取pa指向的值*/n(*pa)+; /*pa所指向的元素的值加1,即(a0)+*/n對于-運(yùn)算同上444.指針與數(shù)組n指針的運(yùn)算n兩個指針的減法運(yùn)算n減法運(yùn)算的含義n當(dāng)兩個指針指向同一數(shù)組中的元素時np-q表示計算兩個指針相差的存儲單元個數(shù)n計算公式為n n提示n只有當(dāng)
38、兩個指針指向同一數(shù)組中的元素時才可進(jìn)行兩個指針的減法運(yùn)算prt1-prt2= (prt1的值的值-prt2的值)的值)/指針的數(shù)據(jù)類型的所占字節(jié)數(shù)指針的數(shù)據(jù)類型的所占字節(jié)數(shù)454.指針與數(shù)組n指針的運(yùn)算n兩個指針的減法運(yùn)算n例:計算一個字符串的長度(不用strlen函數(shù))#include main()() int len; char a80 ; gets(a);); puts(a);); len=lenth(a);); printf(“%dn” ,len);); lenth(char *p) char *q=p; while (*q!=0) q+; return(q-p);); 464.指針與
39、數(shù)組n指針的運(yùn)算n兩個指針的關(guān)系運(yùn)算n比較兩個指針的含義n比較兩個存儲單元的地址(相對位置)n除非兩個指針指向同一數(shù)組,否則這種比較是沒有意義的n比較兩個指向同一數(shù)組的指針反映的是指針?biāo)赶蛟氐南群箜樞騨任何指針p與NULL進(jìn)行“p=NULL”或“p!=NULL”運(yùn)算均有意義n“p=NULL”是當(dāng)指針p為空時成立n“p!=NULL”的含義是當(dāng)p不為空時成立n例如:有兩個指針ptr1和ptr2nif (ptr1ptr2)n printf(“ptr1 points to lower memory than ptr2n”);47例1: 以下程序的輸出結(jié)果是: #include main( ) in
40、t x =10,20,30,40,50,60; int *p=x; *(p+4)+=6; printf(“%d,%d”,8,*(p+4); A) 10,46 B) 0,56 C) 10,56 D) 50,46 例例2: 已知:已知: int a10=1,2,3,4,5,6,7,8,9,10; int *p=a; 則不能表示數(shù)組則不能表示數(shù)組a中元素的表達(dá)中元素的表達(dá) 式是:式是: A)*p B)a10 C)*a D)ap-a4.指針與數(shù)組484.指針與數(shù)組n指針的運(yùn)算n提示n數(shù)組名代表數(shù)組的首地址n固定的,不允許修改的n不能對數(shù)組名采用 +/-操作n指針的算術(shù)運(yùn)算除了應(yīng)用于數(shù)組外沒有什么意義n
41、除數(shù)組外,不能認(rèn)為兩個數(shù)據(jù)類型相同的變量在內(nèi)存中是連續(xù)存儲的n指針的運(yùn)算與其基類型有關(guān)n通常情況下允許一個指針或多個指針指向同一個目標(biāo)n常見錯誤n對不指向數(shù)組的指針進(jìn)行算術(shù)運(yùn)算n指針的運(yùn)算結(jié)果超出的數(shù)組的范圍495.指針與字符串n可以通過字符數(shù)組和字符型指針處理字符串n例如:n字符數(shù)組實現(xiàn)的方式n char ch =“this is a book!” ; n printf (“%sn” ,ch);n對字符數(shù)組初始化nch是字符數(shù)組n它存放了一個字符串n字符指針實現(xiàn)的方式n char *ch=“this is a book!” ;n printf (“%sn” ,ch);n是對字符指針初始化n*
42、ch是字符指針n它指向的是一個字符串常量的首地址,即指向字符串的首地址505.指針與字符串n可以通過字符數(shù)組和字符型指針處理字符串n字符指針與字符數(shù)組區(qū)別nchar *ch字符指針是一個變量n指向字符串的第一個字符n可以改變字符指針使它指向不同的字符串nchar ch 是一個字符數(shù)組n一個足以存放字符串和空字符0的一維數(shù)組n可以改變數(shù)組中保存的內(nèi)容n數(shù)組名 ch是一個不可改變的常量nC語言規(guī)定n一個指針類型的變量如果指向?qū)ο鬄樽址蚽可以對其賦值(或初始化)字符串常量n此時字符指針指向的就是用來保存字符串的字符數(shù)組的首地址515.指針與字符串n可以通過字符數(shù)組和字符型指針處理字符串nC語言規(guī)定
43、n一個指針類型的變量如果指向?qū)ο鬄樽址蚽可以對其賦值(或初始化)字符串常量n此時字符指針指向的就是用來保存字符串的字符數(shù)組的首地址n定義n應(yīng)用n可以使用字符指針指向一個字符類型的數(shù)據(jù)n可以使用字符指針訪問字符串常量(另一種方法為字符數(shù)組)n將“good”賦予指針p并不是將字符串的字符賦予p,n是將“good”在內(nèi)存中的存儲區(qū)的起始地址賦給pmainmain( ) char char * *pcpc;char chchar ch; pc=&ch pc=&ch; scanf scanf(“%c” “%c” ,pcpc);); printf printf(“%c” “%c” ,ch
44、ch);); char char * *p p;p=“good” p=“good” ;525.指針與字符串n字符指針n應(yīng)用n例如np+1作首地址;輸出結(jié)果為bcn提示n賦值時,字符串的結(jié)束標(biāo)志0是系統(tǒng)自動增加的n在輸出或處理字符串指針變量和由字符數(shù)組組成的字符串時只要指出指針變量或字符數(shù)組的名字n對于其它類型的數(shù)組,不能只使用數(shù)組名,輸出或處理全部元素n使用指針編寫的字符串處理程序比使用數(shù)組方式處理字符串的程序更簡潔、更方便n在C語言中,大量使用指針對字符串進(jìn)行各種處理n在處理字符串的函數(shù)中,一般都使用字符指針作為形參 p pp+1p+1 p+2 p+2 a a b b c c00char c
45、har * *p=“abc” p=“abc” ; printf printf(“%s” “%s” ,p+1p+1););535.指針與字符串n指針與字符串的應(yīng)用n例:字符串連接的一個程序n說明n在處理字符串時(包括它作為函數(shù)參數(shù)使用時),只需要指定其變量名,無須指出字符串的長度n對字符串str,若寫成*str則變成了該字符串的第一個字符,表達(dá)式*(str+i)則是表示該字符串的第i+1個字符#include main() char *str1=“People” ; char *str2=“teacher”; char *str3=“n”; strcat(str1,str2); strcat (
46、str1,str3); printf(“%sn”,str1); main()() char *str=“A string!n”; printf(“%s”,str); /*整個字符串操作整個字符串操作*/ for(;*str!=0;) printf(“%c”,*(str+); /*單個字符操作單個字符操作*/ 545.指針與字符串n指針與字符串的應(yīng)用n例:設(shè)計程序,將兩個字符串連接起來n不要用strcat函數(shù)#include main()() char s180,s280 ; printf(“n input string1:”);); gets(s1);); printf(“n input st
47、ring2:”);); gets(s2);); stringcat(s1,s2);); printf(“n new string:%s”,s1);); stringcat(char *s1,char *s2) while (*s1!=0)s1+; while (*s2!=0) *s1=*s2; s1+; s2+; *s1=0; 555.指針與字符串n指針與字符串的應(yīng)用n例:編寫程序判定一個字符在一個字符串中出現(xiàn)的次數(shù),如果該字符不出現(xiàn)則返回0值n算法n從頭開始掃描字符串的每一個字符n若當(dāng)前字符等于字符串中的字符時,次數(shù)計數(shù)器加1n直到字符串中的所有字符比較完成56#include main()
48、() char *str,c; printf(“enter a string:n”);); gets(str);); printf(“enter a char:n”);); c=getchar();(); printf(“counts:%dn” ,char_count(str,c);); int char_count(char *string,char letter) int count=0; while (*string) if (*string+= =letter) count+; return(count);); 5.指針與字符串576.指針與函數(shù)n函數(shù)與指針之間有著密切的關(guān)系n包含三種
49、含義n指針作為函數(shù)的參數(shù)n函數(shù)的返回值為指針n指向函數(shù)的指針 586.指針與函數(shù)n指針作為函數(shù)的參數(shù)n調(diào)用函數(shù)并希望改變參數(shù)的值時,指針做函數(shù)參數(shù)非常實用n按址傳遞n當(dāng)函數(shù)要求能夠修改調(diào)用函數(shù)中的一個或多個值,或能夠傳遞指向大型數(shù)據(jù)對象的地址以避免開銷很大的傳值調(diào)用n通過變量的地址就可以通過地址間接訪問變量的數(shù)值n指針是變量的地址n指針作函數(shù)的參數(shù)就是在函數(shù)間傳遞變量的地址n函數(shù)間傳遞的不再是變量中的數(shù)據(jù),而是變量的地址n變量的地址在調(diào)用函數(shù)時作為實參,被調(diào)用函數(shù)使用指針變量作為形參接收傳遞的地址地址地址實參指針實參指針地址地址形參指針形參指針傳遞傳遞變量的值變量的值變量變量i i地址地址59
50、6.指針與函數(shù)n指針作為函數(shù)的參數(shù)n要求n在調(diào)用函數(shù)時以地址做參數(shù)傳遞n當(dāng)將變量的地址傳遞給被調(diào)函數(shù)后,在調(diào)用函數(shù)的函數(shù)體中采用間接引用運(yùn)算符*修改內(nèi)存單元中的該變量的值n實參的數(shù)據(jù)類型要與作為形參的指針?biāo)傅膶ο蟮臄?shù)據(jù)類型一致n如果是變量的值需要修改,則在變量前面使用&來實現(xiàn)變量的地址n如果是數(shù)組的內(nèi)容需要修改,則直接使用數(shù)組名n常見的錯誤n在需要復(fù)引用(*)一個指針來獲取指針?biāo)赶虻闹禃r沒有復(fù)引用該指針606.指針與函數(shù)n指針作為函數(shù)的參數(shù)n典型例題:比較變量與指針變量的傳遞方式n變量傳遞#include void swap(int p1,int p2);); main()() i
51、nt x1=100,x2=200; printf(“before swap:x1=%d,x2=%d” ,x1,x2);); swap(x1,x2);); printf(“after swap:x1=%d,x2=%d” ,x1,x2);); void swap (int p1,int p2) int temp; temp=p1; p1=p2; p2=temp; 運(yùn)行結(jié)果:運(yùn)行結(jié)果:x1=100,x2=200 x1=100,x2=200 x1=100,x2=200 x1=100,x2=200形參形參p1p1與與p2p2的單元值發(fā)生交換與實參的單元值發(fā)生交換與實參x1x1和和x2x2無關(guān)。無關(guān)。61
52、6.指針與函數(shù)n指針作為函數(shù)的參數(shù)n典型例題:比較變量與指針變量的傳遞方式n指針傳遞#include int swap(int* p1,int* p2);); main()() int x1=100,x2=200; printf(“before swap:x1=%d,x2=%d” ,x1,x2);); swap(&x1,&x2);); printf(“after swap:x1=%d,x2=%d” ,x1,x2);); void swap (int *p1,int *p2)int temp; temp=*p1; *p1=*p2; *p2=temp; 指針作為參數(shù)時并未改變實參的
53、值指針作為參數(shù)時并未改變實參的值而是改變了所指向單元中的內(nèi)容而是改變了所指向單元中的內(nèi)容626.指針與函數(shù)n指針作為函數(shù)的參數(shù)n在主調(diào)函數(shù)中,傳遞的是兩個變量的地址n并沒有試圖改變調(diào)用函數(shù)時的參數(shù),而只是利用了指針變量的特性,改變了指針變量所指向單元的內(nèi)容nswap根據(jù)得到的兩個變量的地址將指針指向的變量中的數(shù)據(jù)進(jìn)行調(diào)換,swap就是在要調(diào)換數(shù)據(jù)的兩個實際變量的存儲單元上進(jìn)行的數(shù)據(jù)交換n交換的結(jié)果自然帶回到主調(diào)函數(shù)main中n問題?n如果將例題中的swap()函數(shù)寫出如下的形式,那么主調(diào)函數(shù)中的實參x1和x2的值能否改變呢?swap(p1,p2) int *p1,*p2; int *temp;
54、 temp=p1; p1=p2; p2=temp; 636.指針與函數(shù)n指針作為函數(shù)的參數(shù)n提示n地址作為函數(shù)的參數(shù)必須定義一個接收地址的指針參數(shù)(形參為指針類型)n例如: void max(int *mptr,int *nptr)n在使用函數(shù)之前先檢查一下函數(shù)原型,確定該函數(shù)是否能夠修改傳遞給它的值n函數(shù)原型中沒有必要指出指針名,但是要指出指針類型n例如:函數(shù)原型void max(int *,int *);n用指針作為函數(shù)參數(shù)并在調(diào)用時傳遞地址作為實參這樣可以改變主調(diào)函數(shù)中變量的值n不能通過改變指針形參的值而使指針實參改變n因為C語言中參數(shù)傳遞具有“單向性”646.指針與函數(shù)n指針作為函數(shù)的
55、參數(shù)n提示n除非主調(diào)函數(shù)明確地要求修被調(diào)函數(shù)環(huán)境中的參數(shù)變量,否則用傳值調(diào)用給函數(shù)傳遞參數(shù)n傳值調(diào)用只能在被調(diào)函數(shù)中修改一個值n要在被調(diào)函數(shù)中修改多個值必須使用傳址調(diào)用n如果傳遞給函數(shù)的值沒有(或不應(yīng)該)在函數(shù)體內(nèi)被修改,應(yīng)該用 const限定符聲明該值以防止被意外地修改n如果試圖在被調(diào)函數(shù)中修改用 const限定符聲明的值,編譯器回給出警告信息或給出錯誤報文n常見錯誤n沒有意識到傳址調(diào)用需要指針做參數(shù),而是把值傳遞給參數(shù)656.指針與函數(shù)n指針作為函數(shù)的參數(shù)n例:輸入三個數(shù),按大小順序排序main() int a,b,c; scanf(“%d%d%d”,&a,&b,&
56、c); exchange(&a,&b,&c); printf(“n%d,%d,%dn”,a,b,c); exchange(p1,p2,p3) int *p1,*p2,*p3; if (*p1*p2) swap(p1,p2); if(*p1*p3) swap(p1,p3); if(*p2*p3) swap(p2,p3); void swap (int *p1,int *p2) int temp; temp=*p1; *p1=*p2; *p2=temp; 666.指針與函數(shù)n指針作為函數(shù)的參數(shù)n例:用傳址方法將字符串中的小寫字母轉(zhuǎn)換為大寫字母。#includevoid convtoupper(char *); main( ) char string=“characters CHARacters”
溫馨提示
- 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)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 工傷代表委托3篇
- 文藝演出技術(shù)服務(wù)咨詢合同3篇
- 新版購銷合同條款3篇
- 房屋買賣家政服務(wù)合同3篇
- 擠密樁灰土施工合同3篇
- 醫(yī)院門衛(wèi)招聘合同范文
- 城市綠化景觀改造與提升合同
- 藝術(shù)廣場幕墻裝飾施工協(xié)議
- 馬術(shù)俱樂部保潔員聘用合同
- 轉(zhuǎn)口貿(mào)易合同中爭議解決方式
- NB-T 47013.7-2012(JB-T 4730.7) 4730.7 承壓設(shè)備無損檢測 第7部分:目視檢測
- 網(wǎng)絡(luò)安全與信息保密培訓(xùn)
- 2023年建筑工程管理經(jīng)理年終總結(jié)及年后展望
- 小學(xué)數(shù)學(xué)問題解決能力的培養(yǎng)策略
- 京歌《故鄉(xiāng)是北京》的藝術(shù)特征及演唱分析
- 機(jī)動庫護(hù)士培訓(xùn)課件
- 客情關(guān)系的有效維護(hù)
- 《班主任工作》教學(xué)大綱
- 新版出口報關(guān)單模板
- 生物研究性學(xué)習(xí)活動結(jié)題報告質(zhì)壁分離
- 堡坎承包合同
評論
0/150
提交評論