東北大學語言課件程序設計基礎08指針_第1頁
東北大學語言課件程序設計基礎08指針_第2頁
東北大學語言課件程序設計基礎08指針_第3頁
東北大學語言課件程序設計基礎08指針_第4頁
東北大學語言課件程序設計基礎08指針_第5頁
已閱讀5頁,還剩71頁未讀, 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

1、程序設計基礎(C語言)東北大學高級語言程序設計課程組課程網站: 程序設計基礎(C語言)指針3n指針是語言的重要概念之一n它使語言比之其它程序設計語言更具特色n深入理解語言特性n指針是學習使用語言的難點n指針是C語言的一個重要概念n正確而靈活地使用指針n有效地描述各種復雜的數據結構n動態(tài)地分配內存空間n自由地在函數之間傳遞各種類型的數據n使程序簡潔、緊湊,執(zhí)行效率高n指針是C提供的一種數據結構n屬于簡單數據類型n它的意義和作用明顯又不同于一般的數據類型概述4A直接直接BA間接間接1.預備知識n直接和間接的含義n內存n即內部存儲器,是由內存單元組成n特點n存儲單元是線性連續(xù)的n存儲單元的最小單位為

2、字節(jié)51.預備知識n內存n計算機的內存中的每一個字節(jié)都有一個編號n所有的內存單元都要統(tǒng)一進行“編號”n這個編號就是該字節(jié)在整個內存中的“地址”n所有的內存單元都要有地址n每一內存單元具有唯一的內存地址n系統(tǒng)為每一個已定義的變量分配一定存儲空間n使變量名與內存的一個地址相對應n通過地址我們就能夠訪問該地址所標識的存儲單元n程序處理過程n需要根據地址取出變量所對應的內存單元中存放的值n參與計算/操作n處理結果存入相應的變量名所對應的內存單元 0 1 2 3 2000 0 1 2 3 2000地址地址4545變量內容變量內容61.預備知識n計算機的尋址方式n直接尋址n間接尋址存入存入/ /取出取出

3、數據數據 數據數據內存內存地址地址 1003 1004 1008 100C 1003 1004 1008 100C 存入存入/ /取出取出B B單元單元內存內存地址地址 1050 1051 3020 3021 1050 1051 3020 3021 地地 址址數據數據 數據數據A A單元單元71.預備知識nC語言如何處理?n高級語言中的變量具有三個屬性n變量的名、變量的值、變量的地址n編程者使用c程序的一個變量n定義變量的數據類型n數據類型決定了一個變量在內存中所占用的存儲空間的大小n變量在內存中總是占用幾個連續(xù)的字節(jié)n定義變量名n語言的編譯系統(tǒng)會根據變量的數據類型為該變量分配內存單元n確定變

4、量的地址n變量的地址就是為變量分配的內存單元的起始編號n就可以通過變量名對內存中變量對應的地址進行操作81.預備知識2000200020022002200120012003200320042004200520052006200620072007地址地址變量名變量名 變量類型變量類型 字節(jié)數字節(jié)數 i int 2 i int 21010a3.14159263.1415926pi float 4 pi float 4 ch char 1 ch char 191.預備知識nC語言如何處理?n直接訪問n通過變量名訪問數據的方式稱為直接訪問 n例如:printf(%d, n); /* 通過變量名訪問變量

5、n */ n間接訪問n如果將變量n的地址存放在另一個變量pn中,通過訪問變量pn,間接達到訪問變量i的目的,這種方式稱為變量的間接訪問 n在C語言中,間接尋址方式訪問內存是通過指針變量實現的n指針變量通過直接尋址方式訪問獲得的是一個地址值n在該地址起始的一個存儲單元中存放程序需要的數據1010101020022002200420041010101030030010121012102.指針變量n定義n用于指向其他變量的變量 n指針變量是一個變量n和普通變量一樣占用一定的存儲空間n該存儲空間存放的是一個地址值而不是普通的數據值n指針變量是一個地址變量n指針變量的值是一個內存單元的地址n它指向另一個

6、變量的值n指針就是地址n當將變量的地址存入指針變量后,就說這個指針指向了該變量n指針變量只能存放某一數據類型的變量n問題?n變量的類型和指向變量的類型之間的區(qū)別?112.指針變量n指針變量的聲明n指針變量與一般的變量的區(qū)別n格式 *指針變量名;n說明n數據類型表示指針所指向的數據的數據類型n提示:不是指針變量的數據類型n*是指針的標志,表示它后面的變量名是指針類型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只有同一數據類型的地 址才能存放在指向該類型變量的指針變量中n例如: int *ip;/*ip指針變量只能存放整型變量的地址*/132.指針變量n指針變量的聲明n提示n在定義指針時可以用void將指針定義為空類型n不指定指針指向一個確定的類型n區(qū)分“值”與“內容”的含義n例如n整型變量是內容為整型數值的變量n整型指針變量是存放整型變量地址的變量n在引用指

8、針變量前必須首先讓指針指向一個變量n這一點非常重要n定義指針變量后,并未確定該變量指向何處,該變量的值是不確定的指針指針P P指針變量指針變量p p的地址的地址內存單元內存單元142.指針變量n指針變量初始化n在使用指針變量時,要首先對指針變量進行初始化,讓指針變量指向一個具體的變量n初始化的方式n使用賦值語句n例nint i, *pi; /* 說明指針變量pa和變量a */pi=&i; /*使用取地址符&把變量i的地址賦值給指針變量:pi指向了整型變量i */ n說明指針變量的時候同時進行n例:使用先聲明變量的地址nint i,*pi=&i;n問題?n寫成int *p

9、a; *pa=&a;會出現什么問題? 152.指針變量n指針變量初始化n在使用指針變量時,要首先對指針變量進行初始化,讓指針變量指向一個具體的變量n初始化的方式n給指針變量賦空值(賦值為符號常量NULL )n例np=NULL;/*表示指針p為空,沒有指向任何對象*/ n一般情況下給沒有初始值的指針變量賦值為NULLn實際上,NULL是整數0,系統(tǒng)保證0單元不存儲任何數據的值(地址)n NULL是頭文件以及其它幾個頭文件中定義的符號常量指針指針P P空地址空地址NULLNULL指針變量指針變量內存單元內存單元162.指針變量n指針變量初始化n提示n在使用指針之前一定要對其進行初始化n否則

10、程序不知道指向何處n系統(tǒng)在執(zhí)行程序時會給出如下的信息nrun-time error R6001null pointer assigmentn或者引起更嚴重的錯誤系統(tǒng)崩潰n對未使用的指針應該賦以空值NULLn表明它未指向任何地方n這并不是對指針的初始化n只是 表示該指針未被使用而已172.指針變量n指針變量初始化n提示n一個指針變量賦空值與不賦值是完全不同的概念n前者是有不指向任何變量的地址n后者是一個不確定的隨機值n這時指針可能指向一個事先未指定的數據n利用空指針可以簡化程序代碼、提高效率n指針變量應具有無符號整型類型的值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但是:不能復引用void*類型的指針n編譯器不能根據類型確定它引用的字節(jié)數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指針變量的運算n語言提供的指針運算n取地址運算(&)n作用是取變量的地址n運算對象必須是(任意類型的)變量n例如n&i /*表示求變量 i的地址*/nint x=3, *p;p=&x /* &表示取的地址,將變量地址賦給指針變量p */n提示n&是一個單目運算符,它返回變量的地址n&的操作數必須是一個變量n取地址運算符“&”是取操作對象的地址而不是其值203.指針變量n

13、指針變量的運算n語言提供的指針運算n取內容運算(*)n運算對象必須是指針(該指針所指向的對象可以是任意類型)n作用是取指針所指向變量的內容。*也稱為“間接引用運算符”或“指針的復引用”n 例如na=*prt; /*表示指針 prt所指向變量的內容賦a*/ nint a=3, *p, x;pa=&a;nx=*pa; /* *pa表示取指針變量pa所指單元的內容,即變量a的值,則x=3 */ 213.指針變量n指針變量的引用n當指針變量定義和賦值之后,引用變量的方式n用變量名直接引用n例如nscanf(“%d”,&a);/*在函數中直接使用變量a的地址 */n通過指向變量的指針間接

14、引用n利用指針變量,提供對變量的一種“間接訪問”形式n指針變量的引用形式 *指針變量 n含義是指針變量所指向的值n例如nint a=3,*pa;pa=&a; /* 指針pa指向變量a*/printf(%dn,*pa); /* 通過 * 運算符實現間接訪問 */223.指針變量n指針變量的引用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 );); 運行結果完全一樣。請思考一下若將程序修改為如下形式:運行結果完全一樣。請思考一下若將程序修改為如下形式:mainmain()() int int * *p p,m m; scanf scanf(“%d”“%d”, p p );); p=&m p=&m; printf printf(“%d”“%d”, m m );); 會產生什么結果?會產生什么結果?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例:本程序演示了指針運算符的用法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的內的內存單元。即存單元。即j j的內存單元中,的內存單元中,P2P2和和p1p1中存放的地址并不發(fā)生變化。中存放的地址并不發(fā)生變化。結果為:結果為: * *p1=10p1=10;* *p2=10p2=10 i=10 i=10;j=20j=20結果:結果: * *p1=10p1=10;* *p2=10p2=10 i=10 i=10;j=10j=103.指針變量25

20、3.指針變量n指針變量的提示n取內容運算符*p與定義指針變量時使用的*p含義不同n定義時的*p表示的是一個指針變量,該變量指向一個整型變量的地址n取內容運算符*p則表示取指針變量的內容,即另一個變量值n對指針的引用需要*和&n&用于求任一類型變量的指針,求出的指針具有對應的類型n*和指針一起使用時被認為是同類型的一個變量n可以參與該類型變量的一切運算n*和&是一對功能恰好相反的運算操作符n在實際應用中, 應特別注意&和*的操作對象n&的操作對象是一個“變量”n*的操作對象是一個“地址”264.指針與數組n指針和數組緊密聯系n對數組元素的訪問可以通過指針和

21、借助數組元素下標的方法實現n凡是由數組下標完成的操作皆可用指針來實現n“下標方式“訪問數組元素n通過數組的下標唯一確定了某個數組元素在數組中的順序和存儲地址n例如:int a5 = 1, 2, 3, 4, 5, x x=a0; /* 通過下標將第1個元素的值賦給x=1 */ 274.指針與數組n指針和數組緊密聯系n對數組元素的訪問可以通過指針和借助數組元素下標的方法實現n凡是由數組下標完成的操作皆可用指針來實現n指針最常見的一種用途就是指向數組元素n當一個指針指向數組后,就可以靈活快速地處理數組元素,從而體現出指針的優(yōu)點n“指針方式”訪問數組中的元素n一個數組(/數組元素)有相應的地址,可以將

22、數組的起始地址或某一個數組元素的地址放到一個指針變量中n數組的指針就是數組的起始地址(數組名),既數組第一個元素的地址(&數組名0)n數組元素的指針就是該數組元素的地址284.指針與數組n指針和數組緊密聯系n分析程序n語言中規(guī)定n數組第1個(下標為0)元素的地址就是數組的首地址n數組名代表的就是數組的首地址n數組名代表的一個地址常量,是數組的首地址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.指針與數組n指針和數組緊密聯系n語言中規(guī)定說明n當指針指向數組首地址時(pt=ary或pt=&ary0時) 指針可以向數組一樣使用n提示n對數組元素的訪問,下標方式和指針方式是等價的n從語言系統(tǒng)內部處理機制上講,指針方式效率高n指針方式不如下標方式直觀n下標方式可以直截了當地看出要訪問的是數組中的哪個元素n指向數組的指針變量,進行運算以后,指針變量的值改變了,其當前指向的是哪一個數組元素不再是一目了然* *(pt+2pt+2)pt2pt2 ary2 ary2 * *(ary+2ary+2)304.指針與

24、數組n指針和數組的可替代性nC語言中的指針和數組幾乎可以互換n指針可以用來完成涉及數組下標的操作n例如:int a10;int *p;n若p=&a0;或 p=a;則p就指向了數組a的首址n當p指向了一維數組a,指針對數組元素可以表示:np+n與a+n( n (偏移量)的取值為09 )表示數組元素 an的地址,既&an n*(p+n)和*(a+n) 表示數組元素an ( n的取值為09 ) n指向數組的指針變量也可以用數組的下標形式pn,其效果相當于*(p+n),等價于an314.指針與數組n指針和數組的可替代性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); 這兩個函數都將一這兩個函數都將一個字符串(可能是個字符串(可能是一個字符數組)拷一個字符數組)拷貝到一個字符數組貝到一個字符數組中,比較這兩個函中,比較這兩個函數

26、原型可以發(fā)現其數原型可以發(fā)現其形式是相同的,雖形式是相同的,雖然這兩個函數完成然這兩個函數完成同樣的功能,但是同樣的功能,但是他們的實現過程是他們的實現過程是不同的。不同的。32/* 采用數組表示法將采用數組表示法將s2拷貝到拷貝到s1.*/void strcopy1(char *s1,const char *s2) int i; for(i=0;s1i=s2i;i+) ; /*函數體中沒有任何動作函數體中沒有任何動作*/ /* 采用指針表示法將采用指針表示法將s2拷貝到拷貝到s1.*/ void strcopy2(char *s1,const char *s2) for( ;*s1=*s2;

27、s1+,s2+) ; /*函數體中沒有任何動作函數體中沒有任何動作*/ 4.指針與數組334.指針與數組n指針和數組的可替代性n數組的表示法n數組/下標n指針/偏移量n利用*p、*(p+1)、來代表數組a0、a1n數組/偏移量n對數組的引用以*a、*(a+ 1)、代替a0、a9n n指針/下標n表達式p1引用了數組元素a134【例【例1 1 】采用指針】采用指針/ /偏移量表示的地址法輸入輸出數組元素。偏移量表示的地址法輸入輸出數組元素。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】采用表示的數組】采用表示的數組/ /偏移量表示的地址法輸入輸出數組元素。偏移量表示的地址法輸入輸出數組元素。 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.指針與數組35【例【例3 3】采用指針】采用指針/ /下標法輸入輸出數組元素。下標法輸入輸出數組元素。 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】采用數組】采用數組/ /下標法輸入輸出數組元素。下標法輸入輸出數組元素。 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.指針與數組36mainmain()()int ary4=int ary4=2,4,8,162,4,8,16; int int * *iprtiprt,i i; iprt=ary iprt=ary; / /* *按正序輸出數組元素按正序輸出數組元素* */ / for for (i=0i=0;i4i=0i=0;i- -i- -) printf printf(“%d” “%d” ,* *( iprt+i iprt+

32、i );); prntf prntf(“n”“n”);); 4.指針與數組n指針和數組的可替代性n例:將一個數組按正向、逆向輸出374.指針與數組n指針和數組的關系n提示n指針變量與數組的區(qū)別n指針變量是地址變量,數組名是地址常量n指針變量的內容可以在程序運行過程中被修改,數組名一旦被聲明,它的值在整個程序運行中是不能改變n(p+1)和 *(a+ 1)都可以表示數組元素a1, 兩者并不能完全等價n對 數組a只能引用,不能修改n實際上就是指針與指針變量的區(qū)別n對于數組名,雖然可以使用它得到其元素的值,但它僅表示數組的首地址,不能將其改變n試圖用指針算術運算修改數組名是一種語法錯誤384.指針與數

33、組n指針和數組的關系n提示n指針變量與數組的區(qū)別n指針變量可以改變其自身的值,應該特別注意其的當前值n 例如:對上例程序中的a和pa,若有程序段:n pa=a;printf(”%dn”,*pa);n pa+;printf(“%dn”,*pa);n第一個printf輸出的是a0的值n第二個printf則輸出的是a1的值n指向數組的指針在數組處理時不要越界n由于C語言不檢查數組越界,對一個僅有10個元素的數組a引用第11個元素a10時系統(tǒng)仍按 *(a+10)處理,發(fā)生錯誤394.指針與數組n指針的運算n指針的運算旨在針對數組進行n指針的運算n指針與正整數的加減運算n兩個指針的減法運算n兩個指針的關

34、系運算n禁止的運算n指針做乘除法運算n指針進行位操作運算n指針與浮點型數據運算n兩個指針相加沒有意義n指針運算的結果依賴于指針所指向對象的大小n指向對象的數據類型404.指針與數組n指針的運算n指針與正整數的加減運算n該指針下移或上移整型值所指定個數的存儲單元的內存地址n存儲單元的大小就是該指針的數據類型所需要的內存的大小np+(-)i*sizeof(type)n對指針的加/減(整數)操作運算在用指針訪問數組元素是經常用到n表達式:p+n表示指針p所指向當前元素之后的第n個元素n而表達式:p-n表示指針p所指向當前元素之前的第n個元素指針變量指針變量ptr內存內存地址地址20002001200

35、2200320042005200620072008414.指針與數組n指針的運算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.指針與數組n指針的運算n指針與正整數的加減運算n自增/自減n指針的自增(+)/自減(-)運算分別表示將指針移動到下一個/上一個存儲單元并指向新的數據np+的含義n指針加,指向數組中的下一個元素np-的含義n

36、指針減,指向數組中的前一個元素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.指針與數組n指針的運算n提示n例如:in

37、t a5,*pa:pa=a;npa+; /*使pa指向下一個元素a1;*/n*pa; /*指針所指向的數組名(或變量或數組元素)*/n*pa+; /*先取出pa所指向元素的值 (*pa),后pa+1送 n 與pa。由于+與*的優(yōu)先級相同,自右向左的結 n 合方向,所以它等價于*(pa+);*/n*(+pa);/*先令pa加1,再取pa指向的值*/n(*pa)+; /*pa所指向的元素的值加1,即(a0)+*/n對于-運算同上444.指針與數組n指針的運算n兩個指針的減法運算n減法運算的含義n當兩個指針指向同一數組中的元素時np-q表示計算兩個指針相差的存儲單元個數n計算公式為n n提示n只有當

38、兩個指針指向同一數組中的元素時才可進行兩個指針的減法運算prt1-prt2= (prt1的值的值-prt2的值)的值)/指針的數據類型的所占字節(jié)數指針的數據類型的所占字節(jié)數454.指針與數組n指針的運算n兩個指針的減法運算n例:計算一個字符串的長度(不用strlen函數)#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、數組n指針的運算n兩個指針的關系運算n比較兩個指針的含義n比較兩個存儲單元的地址(相對位置)n除非兩個指針指向同一數組,否則這種比較是沒有意義的n比較兩個指向同一數組的指針反映的是指針所指向元素的先后順序n任何指針p與NULL進行“p=NULL”或“p!=NULL”運算均有意義n“p=NULL”是當指針p為空時成立n“p!=NULL”的含義是當p不為空時成立n例如:有兩個指針ptr1和ptr2nif (ptr1ptr2)n printf(“ptr1 points to lower memory than ptr2n”);47例1: 以下程序的輸出結果是: #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; 則不能表示數組則不能表示數組a中元素的表達中元素的表達 式是:式是: A)*p B)a10 C)*a D)ap-a4.指針與數組484.指針與數組n指針的運算n提示n數組名代表數組的首地址n固定的,不允許修改的n不能對數組名采用 +/-操作n指針的算術運算除了應用于數組外沒有什么意義n

41、除數組外,不能認為兩個數據類型相同的變量在內存中是連續(xù)存儲的n指針的運算與其基類型有關n通常情況下允許一個指針或多個指針指向同一個目標n常見錯誤n對不指向數組的指針進行算術運算n指針的運算結果超出的數組的范圍495.指針與字符串n可以通過字符數組和字符型指針處理字符串n例如:n字符數組實現的方式n char ch =“this is a book!” ; n printf (“%sn” ,ch);n對字符數組初始化nch是字符數組n它存放了一個字符串n字符指針實現的方式n char *ch=“this is a book!” ;n printf (“%sn” ,ch);n是對字符指針初始化n*

42、ch是字符指針n它指向的是一個字符串常量的首地址,即指向字符串的首地址505.指針與字符串n可以通過字符數組和字符型指針處理字符串n字符指針與字符數組區(qū)別nchar *ch字符指針是一個變量n指向字符串的第一個字符n可以改變字符指針使它指向不同的字符串nchar ch 是一個字符數組n一個足以存放字符串和空字符0的一維數組n可以改變數組中保存的內容n數組名 ch是一個不可改變的常量nC語言規(guī)定n一個指針類型的變量如果指向對象為字符型n可以對其賦值(或初始化)字符串常量n此時字符指針指向的就是用來保存字符串的字符數組的首地址515.指針與字符串n可以通過字符數組和字符型指針處理字符串nC語言規(guī)定

43、n一個指針類型的變量如果指向對象為字符型n可以對其賦值(或初始化)字符串常量n此時字符指針指向的就是用來保存字符串的字符數組的首地址n定義n應用n可以使用字符指針指向一個字符類型的數據n可以使用字符指針訪問字符串常量(另一種方法為字符數組)n將“good”賦予指針p并不是將字符串的字符賦予p,n是將“good”在內存中的存儲區(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應用n例如np+1作首地址;輸出結果為bcn提示n賦值時,字符串的結束標志0是系統(tǒng)自動增加的n在輸出或處理字符串指針變量和由字符數組組成的字符串時只要指出指針變量或字符數組的名字n對于其它類型的數組,不能只使用數組名,輸出或處理全部元素n使用指針編寫的字符串處理程序比使用數組方式處理字符串的程序更簡潔、更方便n在C語言中,大量使用指針對字符串進行各種處理n在處理字符串的函數中,一般都使用字符指針作為形參 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指針與字符串的應用n例:字符串連接的一個程序n說明n在處理字符串時(包括它作為函數參數使用時),只需要指定其變量名,無須指出字符串的長度n對字符串str,若寫成*str則變成了該字符串的第一個字符,表達式*(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指針與字符串的應用n例:設計程序,將兩個字符串連接起來n不要用strcat函數#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指針與字符串的應用n例:編寫程序判定一個字符在一個字符串中出現的次數,如果該字符不出現則返回0值n算法n從頭開始掃描字符串的每一個字符n若當前字符等于字符串中的字符時,次數計數器加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.指針與函數n函數與指針之間有著密切的關系n包含三種

49、含義n指針作為函數的參數n函數的返回值為指針n指向函數的指針 586.指針與函數n指針作為函數的參數n調用函數并希望改變參數的值時,指針做函數參數非常實用n按址傳遞n當函數要求能夠修改調用函數中的一個或多個值,或能夠傳遞指向大型數據對象的地址以避免開銷很大的傳值調用n通過變量的地址就可以通過地址間接訪問變量的數值n指針是變量的地址n指針作函數的參數就是在函數間傳遞變量的地址n函數間傳遞的不再是變量中的數據,而是變量的地址n變量的地址在調用函數時作為實參,被調用函數使用指針變量作為形參接收傳遞的地址地址地址實參指針實參指針地址地址形參指針形參指針傳遞傳遞變量的值變量的值變量變量i i地址地址59

50、6.指針與函數n指針作為函數的參數n要求n在調用函數時以地址做參數傳遞n當將變量的地址傳遞給被調函數后,在調用函數的函數體中采用間接引用運算符*修改內存單元中的該變量的值n實參的數據類型要與作為形參的指針所指的對象的數據類型一致n如果是變量的值需要修改,則在變量前面使用&來實現變量的地址n如果是數組的內容需要修改,則直接使用數組名n常見的錯誤n在需要復引用(*)一個指針來獲取指針所指向的值時沒有復引用該指針606.指針與函數n指針作為函數的參數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; 運行結果:運行結果:x1=100,x2=200 x1=100,x2=200 x1=100,x2=200 x1=100,x2=200形參形參p1p1與與p2p2的單元值發(fā)生交換與實參的單元值發(fā)生交換與實參x1x1和和x2x2無關。無關。61

52、6.指針與函數n指針作為函數的參數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; 指針作為參數時并未改變實參的

53、值指針作為參數時并未改變實參的值而是改變了所指向單元中的內容而是改變了所指向單元中的內容626.指針與函數n指針作為函數的參數n在主調函數中,傳遞的是兩個變量的地址n并沒有試圖改變調用函數時的參數,而只是利用了指針變量的特性,改變了指針變量所指向單元的內容nswap根據得到的兩個變量的地址將指針指向的變量中的數據進行調換,swap就是在要調換數據的兩個實際變量的存儲單元上進行的數據交換n交換的結果自然帶回到主調函數main中n問題?n如果將例題中的swap()函數寫出如下的形式,那么主調函數中的實參x1和x2的值能否改變呢?swap(p1,p2) int *p1,*p2; int *temp;

54、 temp=p1; p1=p2; p2=temp; 636.指針與函數n指針作為函數的參數n提示n地址作為函數的參數必須定義一個接收地址的指針參數(形參為指針類型)n例如: void max(int *mptr,int *nptr)n在使用函數之前先檢查一下函數原型,確定該函數是否能夠修改傳遞給它的值n函數原型中沒有必要指出指針名,但是要指出指針類型n例如:函數原型void max(int *,int *);n用指針作為函數參數并在調用時傳遞地址作為實參這樣可以改變主調函數中變量的值n不能通過改變指針形參的值而使指針實參改變n因為C語言中參數傳遞具有“單向性”646.指針與函數n指針作為函數的

55、參數n提示n除非主調函數明確地要求修被調函數環(huán)境中的參數變量,否則用傳值調用給函數傳遞參數n傳值調用只能在被調函數中修改一個值n要在被調函數中修改多個值必須使用傳址調用n如果傳遞給函數的值沒有(或不應該)在函數體內被修改,應該用 const限定符聲明該值以防止被意外地修改n如果試圖在被調函數中修改用 const限定符聲明的值,編譯器回給出警告信息或給出錯誤報文n常見錯誤n沒有意識到傳址調用需要指針做參數,而是把值傳遞給參數656.指針與函數n指針作為函數的參數n例:輸入三個數,按大小順序排序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.指針與函數n指針作為函數的參數n例:用傳址方法將字符串中的小寫字母轉換為大寫字母。#includevoid convtoupper(char *); main( ) char string=“characters CHARacters”

溫馨提示

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

評論

0/150

提交評論