版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
C語言程序設(shè)計A課程輔導(dǎo)(5)---第5章指針重要內(nèi)容:一、指針的概念二、指針變量三、指針運算四、指針與數(shù)組五、動態(tài)存儲分派六、使用指針和動態(tài)存儲分派的程序舉例一、指針的概念指針:計算機(jī)內(nèi)部存儲器中一個存儲(單元)字節(jié)的地址。該地址是一個32位的二進(jìn)制編碼,所占有的字節(jié)數(shù)(指針類型長度)與int類型長度相同。指針是一種特殊的數(shù)據(jù),即不是字符和常數(shù),而是內(nèi)存單元的編碼(地址)。指針與數(shù)據(jù)類型:在C語言中每個指針都與一個具體的數(shù)據(jù)類型相聯(lián)系,即為內(nèi)存中存儲該類型的一個數(shù)據(jù)的地址,具體為數(shù)據(jù)所占用存儲空間(又稱為存儲單元或數(shù)據(jù)單元)的首字節(jié)地址。如intx=10;則x的地址就是一個指針,它是存儲x的值10的4個存儲字節(jié)的第一個字節(jié)的地址。指針類型:就是它所指向的存儲單元中所存數(shù)據(jù)的類型。如一個指針指向一個整型數(shù)(即所指向的存儲單元中存儲的是整數(shù)),則稱為整型指針;若指向一個字符,則成為字符指針。數(shù)據(jù)地址的表達(dá):在一個變量前加上&字符,就表達(dá)取該變量的地址,該地址(指針)的類型就是該數(shù)據(jù)的類型。如intx;&x就表達(dá)x的地址,其類型為int指針類型,可表達(dá)為int*??罩羔槪浩渲禐?的指針稱為空指針??罩羔槻恢赶蛉魏螖?shù)據(jù),在stdio.h頭文獻(xiàn)中已經(jīng)把NULL定義為0,所以符號常量NULL也表達(dá)為空指針。二、指針變量可以保存存儲單元地址的變量。一般變量保存的是字符或常數(shù)。定義格式:<類型關(guān)鍵字>*<指針變量名>[=<指針表達(dá)式>],...;與一般變量定義語句格式基本相同,只要在變量標(biāo)記符前加上*即為指針變量。格式舉例:(1)intx,*p;//定義x為int型一般變量,p為int*型指針變量(2)inta=10,*pa=&a;//定義int變量a并初始化10,同時定義pa為//int*類型的指針變量,并初始化為a的地址,即整數(shù)變量的地址(3)char*p1=0,*p2="pointer";//p1為空,p2指向字符串"pointer"http://把"pointer"的第1個字符的地址賦給指針變量p2,類型為char*(4)char*d[5]={0};//字符數(shù)組d[5]中每個元素均為指針變量,其值為空(5)intx=5,*px=&x,**pp=&px;//px:int*類型,pp:int**類型pppxx&px&x5//px的地址具有int**類型(6)char*rp[3]={"front","middle","rear"};//定義指針數(shù)組和初始化(7)inta[10],*ps=a;//數(shù)組名a的值是第1個元素的地址,//即a[0]元素的地址&a[0],類型為int*輸出一般指針和輸出字符指針?biāo)赶虻淖址狠敵鲆话阒羔槙r使用的格式符為"%p",輸出字符指針?biāo)赶虻淖址畷r使用的格式符為"%s"。例如:#include<stdio.h>voidmain(){inta=30;char*cp;//可以保存一個字符變量或數(shù)組元素的地址cp="output";//cp指向字符串常量"output"printf("%p%p\n",&a,cp);//輸出指針,分別為a和'o'的地址printf("%d%s\n",a,cp);//輸出a的值和cp所指向的字符串}運營結(jié)果:0013FF7C0042023C//十六進(jìn)制8位30output向字符指針輸入字符串:chara[30];scanf("%s",a);//gets(a);chara[30],*p=a;scanf("%s",p);//gets(p);運用typedef語句定義指針數(shù)據(jù)類型:(1)typedefint*inPointer;//定義inPointer為int*類型,//若用inPointers1=NULL;等價于int*s1=NULL;(2)typedefchar*chPointer;//定義chPointer為char*類型(3)typedefchar*AA[10];//定義AA為char*[10]指針數(shù)組類型,//若用AAaa;等價于char*aa[10];三、指針運算
涉及賦值、取地址、間接訪問、增減1等。賦值(=)雙目運算,把賦值號右邊的指針(地址)值賦給左邊的同類型的指針變量。intx=30,*px,*py;px=&x;py=px;//把x的地址賦給px,把px值賦給py,它們均指向x取地址(&)單目運算,使用在一般變量的前面,表達(dá)取變量的地址。charch='+',*p=&ch;//取ch變量的地址賦給p,p指向chchars[30]="Apple",*ps=s;//字符數(shù)組s的地址賦給ps,ps指向s,//s和ps的值均為s數(shù)組中第1個元素'A'的存儲地址間接訪問(*)在指針前面使用*運算符可以訪問到指針?biāo)赶虻膶ο?。如:intx=12,*px=&x;//px指向x,px所指向的對象x的值為12printf("%d\n",*px+10);//22,使用*px+10等同于x+10*px+=15;//27,使用*px+=15等同于x+=15,*px即x的值變?yōu)?7增1(++)和減1(--)單目運算,可使用在指針變量的前面或后面,使指針變量的值增1或減1。inta[5]={10,15,20,25,30},x,y;int*p=a;//p指向a[0]元素,即p的值為a[0]的地址x=*p++;//x的值為10,p加1后賦給p,p指向下一個元素a[1]x=*++p;//x的值為20,p指向元素a[2]y=(*p)++;//y的值為20,a[2]被加1后賦給a[2],a[2]的值變21p--;//運算前p指向a[2],運算后p指向a[1]printf("%d\n",*p--);//輸出a[1]的值15,然后p減1后指向a[0]p=&a[3];printf("%d\n",--*p);//*p的值25,輸出減1后的a[3]的值24注意:當(dāng)指針變量p指向數(shù)組中的一個元素時,p++或++p則使p指向其下一個元素,p—或—p則使p指向其前一個元素。若p指向a[i],則進(jìn)行p++或++p運算后,p指向a[i+1];若p指向a[i],則進(jìn)行p--或--p運算后,p指向a[i-1]。加(+)和減(-)雙目運算,使指針向后或向前移動若干個數(shù)據(jù)位置。intb[6]={1,3,5,7,9,11};int*p=b,*q=p+5;//p指向b[0],q指向b[5],p+5等同于b+5printf("%d\n",*(q-3));//輸出b[2]的值5p=b+6;//p指向b[6]數(shù)組后面的一個數(shù)據(jù)單元,即b[5]后的位置*--p;//取b[5]元素的值11加賦值(+=)和減賦值(-=)雙目運算,左邊的指針變量加上或減去右邊相應(yīng)的值。chara[20]="wbcdefghi";char*p=a;//p指向a[0],即字符wp+=7;//運算后p指向a[7],即字符hp-=4;//運算后p指向a[3],即字符d*p-=3;//運算后使a[3]的值減3,由100(d的ASCII碼)變?yōu)?7(a的碼)比較(==,!=,<,<=,>,>=)雙目運算,比較左右兩個指針(地址)的大小。數(shù)組中后面元素的指針大于前面元素的指針,即&a[i+1]>&a[i]。inta[5]={20,15,32,48,46};int*p;for(p=a;p<a+5;p++)printf("%d",*p);//依次輸出a中每個元素值for(p=a+4;p>=a;p--)printf("%d",*p);//逆序輸出a中每個元素值這一講就到這里,同學(xué)們再見!四、指針與數(shù)組1.指針與一維數(shù)組一維數(shù)組名是指向該數(shù)組第一個元素的指針常量12251830634450inta[7]={12,25,18,30,63,44,50};0123456a*a表達(dá)a[0]元素,*a的值即為a[0]的值。a的值等于&a[0],類型int*。a為指針常量,即其值不可修改,所以使用a++是錯誤的。道理很簡樸,假如允許修改數(shù)組名的值,以后就無法訪問該數(shù)組了。數(shù)組元素的下標(biāo)和指針訪問方式a[i]等價于*(a+i),分別為下標(biāo)和指針訪問方式。*a與a[0],*(a+1)與a[1]等價。假定int*p=a+i;則*p與a[i],*p++與a[i++]等價。for(i=0;i<7;i++)printf("%5d\n",a[i]);//下標(biāo)方式等價于:for(i=0;i<7;i++)printf("%5d\n",*(a+i));//指針方式等價于:for(p=a;p<a+7;p++)printf("%5d\n",*p);//指針方式等價于:for(p=a,i=0;i<7;i++)printf("%5d\n",p[i]);//下標(biāo)方式//p初始指向數(shù)組a中第1個元素,p[i]與a[i]等價,均為*(a+i)2.指針與二維數(shù)組二維數(shù)組名是指向該數(shù)組第一行元素的指針常量,其值為整個二維數(shù)組空間的首地址intb[3][4]={{1,2,3,4},{2,4,6,8},{3,6,9,12}};b為指向b[0]行4個元素的指針常量,其值為&b[0],亦即&b[0][0]的值,但類型為int(*)[4],而不是int*。b[i]為i行元素(一維數(shù)組)的數(shù)組名,b[i]的值為b[i][0]元素的地址。它們的類型均為int*。而&b[i]的值雖然也等于b[i][0]元素的地址,但類型為int(*)[4],由于它是該行元素的首地址。同一維數(shù)組名同樣,不允許修改二維數(shù)組名的值,如進(jìn)行b++操作是錯誤的。二維數(shù)組名的值可以賦給同類型的指針變量int(*pb)[4]=b;//把b的值賦給同類型的指針變量pb,pb也指向此數(shù)組,//此后pb也可以作為數(shù)組名使用,訪問任何元素pb[2][3]等價與b[2][3],值為12。注意:int(*pb)[4]與int(*pb)[5]不同,由于pb所指向的元素個數(shù)不同。若int*pb[4]的則定義pb為具有4個元素的整型指針數(shù)組,而不是定義指向具有4個整型元素的數(shù)組的指針。二維數(shù)組元素的下標(biāo)和指針訪問方式b[i][j](*(b+i))[j]或*(b[i]+j)或*(*(b+i)+j)//均等價for(i=0;i<3;i++){for(j=0;j<4;j++)printf("%d",b[i][j]);//*(*(b+i)+j)printf("\n");}使用指針和數(shù)組的程序舉例例1:#include<stdio.h>voidmain(){inta[8]={3,5,7,9,11,13,15,17};inti,*p=a;//p的值為&a[0]for(i=0;i<8;i++){printf("%5d",*p++);//先*p,后p的值加1if((i+1)%4==0)printf("\n");//輸出4個元素后換行}}輸出結(jié)果:357911131517例2:#include<stdio.h>voidmain(){inta[8]={46,38,72,55,24,63,50,37};intmax=*a,min=*a;//a[0]的值賦給max和minint*p;for(p=a+1;p<a+8;p++){//掃描整個數(shù)組if(*p>max)max=*p;//大放maxif(*p<min)min=*p;//小放min}printf("%5d%5d\n",max,min);//輸出最大和最小值}輸出結(jié)果:7224五、動態(tài)存儲分派1.動態(tài)存儲分派的概念變量和數(shù)組在計算機(jī)內(nèi)存中都有相應(yīng)的存儲空間,該存儲空間的分派時機(jī)有兩種:一種在編譯階段,或者說在程序運營前;另一種在程序運營之中。前者稱為靜態(tài)存儲分派方式,后者稱為動態(tài)存儲分派方式。變量的靜態(tài)存儲分派方式通過一般的變量定義語句定義的變量,采用的是靜態(tài)存儲分派方式。如:intx,y;//x和y分別相應(yīng)的4個字節(jié)的存儲空間是靜態(tài)分派的inta[10];//數(shù)組a所需要的40個字節(jié)的存儲空間是靜態(tài)分派的charb[20],*p=b;//數(shù)組b的20個字節(jié)和指針變量p的4字節(jié)是靜態(tài)分派的doublec[M][N]={{0}};//數(shù)組c的M*N*8個字節(jié)的存儲空間是靜態(tài)分派的變量的動態(tài)存儲分派方式變量的動態(tài)存儲分派需要調(diào)用在系統(tǒng)頭文獻(xiàn)stdlib.h中聲明的動態(tài)存儲分派函數(shù)來實現(xiàn),這些函數(shù)為malloc()、calloc()和realloc()三種。2.動態(tài)存儲分派函數(shù)的原型格式和功能malloc()函數(shù)原型格式void*malloc(unsignedintk);功能:調(diào)用它時可以分派k個字節(jié)的存儲空間,并把第1個字節(jié)的地址返回,該返回值具有void*類型,可以賦給任一具體類型的指針變量。calloc()函數(shù)原型格式void*calloc(unsignedintn,unsignedintk);功能:調(diào)用它時可以分派n*k個字節(jié)的存儲空間,并把第1個字節(jié)的地址返回,該返回值具有void*類型,可以賦給任一具體類型的指針變量。通常用n表達(dá)數(shù)組長度,k表達(dá)元素類型的長度。realloc()函數(shù)原型格式void*realloc(void*ptr,unsignedintk);功能:調(diào)用它時可以分派k個字節(jié)的存儲空間,接著把ptr已經(jīng)指向的動態(tài)分派的存儲空間的內(nèi)容復(fù)制到新分派的存儲空間中,最后把新分派的存儲空間的第1個字節(jié)的地址返回。由于該返回值具有void*類型,所以可以賦給任一具體類型的指針變量,通常仍賦給ptr所相應(yīng)的實參指針變量,使得通過該調(diào)用后增長或縮小動態(tài)存儲空間。3.動態(tài)存儲分派的調(diào)用格式舉例(1)int*pn=malloc(sizeof(int));//分派一個整數(shù)存儲空間由指針變量pn所指向,此動態(tài)分派的變量//為*px,可用它保存一個整數(shù),如:*px=25;*px+=30;//其值為55(2)double*pa=calloc(10,sizeof(double));//分派一個具有10個雙精度元素的一維數(shù)組空間,由指針變量pa//所指向,pa也就是該動態(tài)數(shù)組的數(shù)組名(但有區(qū)別,它是變不是常),//通過它可以訪問該數(shù)組中的任何元素。如:*pa=12;把12賦給//pa[0]元素;又如:pa[i]<pa[j]進(jìn)行兩元素大小的比較(3)pa=realloc(pa,20*sizeof(double));//增長pa指針?biāo)赶虻拇鎯臻g的大小,由10個雙精度元素變?yōu)?/20個雙精度元素,同時原有的存儲內(nèi)容被復(fù)制過來。(4)int**top=calloc(M+1,sizeof(int*));//top動態(tài)數(shù)組具有M+1個元素,每個元素可以存儲一個整數(shù)的地址。4.動態(tài)存儲分派的優(yōu)點允許在程序運營過程中隨時擬定待使用的存儲空間的大小,不必象靜態(tài)分派那樣需要事先擬定。一般定義一個數(shù)組時,必須確切給出數(shù)組的每一維的尺寸,如:inta[10],b[M][N];//M和N必須是已經(jīng)定義的符號常量動態(tài)分派定義一個數(shù)組時,所分派的存儲空間的大小可以是常量,也可以是變量。如:(1)inta=calloc(10,4);//兩個參數(shù)都為常量(2)inta=calloc(x,4);//第1個參數(shù)為變量,分派x個整數(shù)元素的空間(3)charb=malloc(n1+n2);//n1和n2為變量,分派n1+n2個字節(jié)的空間(4)charc=malloc(sizeof(d));//根據(jù)另一個對象d的大小分派空間5.動態(tài)存儲空間的釋放釋放動態(tài)存儲空間的free()函數(shù)的原型格式voidfree(void*ptr);功能:調(diào)用它時可以把指針變量ptr所指向的動態(tài)存儲空間釋放掉,即歸還給操作系統(tǒng)。free()函數(shù)原型聲明也包含在stdlib.h系統(tǒng)頭文獻(xiàn)中當(dāng)動態(tài)存儲空間保存的內(nèi)容不再使用時,可調(diào)用該free()函數(shù)及時釋放掉,若沒有調(diào)用它,則一直到程序運營結(jié)束時該動態(tài)存儲空間才被自動釋放給操作系統(tǒng)。對于一般靜態(tài)分派的變量,其占有的存儲空間只能由C語言系統(tǒng)在運營時自動釋放,其時機(jī)為所在的模塊(復(fù)合語句)剛執(zhí)行完畢。下面看一個程序例子#include<stdio.h>//支持調(diào)用標(biāo)準(zhǔn)輸入和輸出操作的函數(shù)#include<stdlib.h>//支持調(diào)用動態(tài)存儲分派和釋放函數(shù)voidmain(){int*a=calloc(10,sizeof(int));//動態(tài)分派得到a[10]數(shù)組,//為40字節(jié)的存儲空間,同時靜態(tài)分派得到a指針變量,4字節(jié)inti;//靜態(tài)分派得到i整數(shù)變量,4字節(jié)for(i=0;i<10;i++)a[i]=i*i;//給a數(shù)組中每個元素賦值for(i=0;i<10;i++)printf("%d",a[i]);//輸出a中每個元素值printf("\n");//輸出一個換行符free(a);//a[10]數(shù)組的40個字節(jié)的動態(tài)存儲空間被交還給操作系統(tǒng)}//此主函數(shù)執(zhí)行結(jié)束時,自動把a和i各占有的4字節(jié)交還給操作系統(tǒng)程序運營結(jié)果:0149162536496481六、使用指針和動態(tài)存儲分派的程序舉例例1:以指針方式訪問數(shù)組元素的例子#include<stdio.h>#include<stdlib.h>voidmain(){inta[5]={3,6,9,12,15};int*p=a;//把數(shù)組a的首地址賦給指針變量pinti;for(i=0;i<5;i++)printf("%5d",*p++);//指針方式訪問數(shù)組aprintf("\n");//換行for(p=a+4;p>=a;p--)printf("%5d",*p);//從后向前訪問數(shù)組元素printf("\n");//換行}輸出結(jié)果:36912151512963例2:進(jìn)行簡樸變量動態(tài)存儲分派的例子#include<stdio.h>#include<stdlib.h>voidmain(){intx=23,y=40,z;int*p1=malloc(sizeof(int));//為*p1動態(tài)分派4字節(jié)存儲空間int*p2=malloc(sizeof(int));//為*p2動態(tài)分派4字節(jié)存儲空間*p1=x;*p2=y;//分別把x值23和y值40賦給動態(tài)變量*p1和*p2printf("%d%d\n",*p1,*p2);//輸出*p1和*p2的值為2340z=*p1;*p1=*p2;*p2=z;//互換*p1和*p2所保存的值printf("%d%d\n",*p1,*p2);//輸出*p1和*p2的值為4023free(p1);free(p2);//釋放p1和p2各自所指向的動態(tài)存儲空間}程序運營結(jié)果:23404023例3:動態(tài)存儲分派任意大小的一維數(shù)組的例子#include<stdio.h>#include<stdlib.h>voidmain(){intn,i,sum=0;int*a;printf("從鍵盤給n輸入一個正整數(shù)(1-10):");while(1){scanf("%d",&n);//輸入1-10之間的數(shù)到n中if(n>=1&&n<=10)break;elseprintf("重輸:");}a=calloc(n,sizeof(int));//動態(tài)分派a[n]數(shù)組空間,n是變量a[0]=0;a[1]=1;//給a數(shù)組的前2個元素賦值for(i=2;i<n;i++)a[i]=a[i-1]+a[i-2];//從元素a[2]起,每個元素值等于前2個元素值之和//0+1=1,1+1=2,1+2=3,2+3=5,…for(i=0;i<n;i++){sum+=a[i];//計算出n個元素之和printf("
溫馨提示
- 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)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 高中物理第九章固體液體和物態(tài)變化第2節(jié)液體課件新人教版選修3-
- 高考數(shù)學(xué)全真模擬試題第12625期
- 【中考考點基礎(chǔ)練】第11章 內(nèi)能與熱機(jī) 2025年物理中考總復(fù)習(xí)(福建)(含答案)
- 2024年山東省泰安市中考地理試題含答案
- 2024至2030年中國無菌設(shè)備數(shù)據(jù)監(jiān)測研究報告
- 2024至2030年中國數(shù)碼固體立體聲全自動播放器數(shù)據(jù)監(jiān)測研究報告
- 2024至2030年中國微電腦控制抽真空精密加酸機(jī)數(shù)據(jù)監(jiān)測研究報告
- 2024至2030年中國引線式熱敏電阻器行業(yè)投資前景及策略咨詢研究報告
- 2010-2012年液態(tài)豆奶行業(yè)市場研究與競爭力分析報告
- 2024至2030年中國土堿行業(yè)投資前景及策略咨詢研究報告
- 電動單梁起重機(jī)年自檢報告
- 鄉(xiāng)鎮(zhèn)結(jié)核病防治工作職責(zé)
- 模擬深海高壓艙試驗系統(tǒng)設(shè)計方案
- 加熱管制作工藝
- 互補輸出級介紹
- 設(shè)備運輸方案
- (完整版)管道代號對照
- 口腔頜面部外傷的救治2
- 市森林消防(防汛)專業(yè)隊管理制度森林防火撲火隊管理制度.doc
- 路緣石拆除更換專項施工方案(精華版)
- 正交試驗設(shè)計表.doc
評論
0/150
提交評論