版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
指針C語言程序設(shè)計目錄content指針的基本概念1指針運算2指針與數(shù)組3指針數(shù)組與多級指針4指針與函數(shù)5綜合應(yīng)用6內(nèi)存的地址例:int*px,x;px=&x;6.1.1指針的基本概念指針指針變量指針常量指針是一種數(shù)據(jù)類型變量的地址裝入指針指針指向變量指針的目標變量x是px的目標變量
變量的訪問方式直接訪問方式x=10;間接訪問方式*px=10;6.1.2指針變量的定義與初始化指針變量的定義<存儲類型><數(shù)據(jù)類型>*指針名;例如:int*px;char*name;staticint*pa;int*px,*py,*pz;charcc,*name;具有相同存儲類型和數(shù)據(jù)類型的指針可在一行中說明,也可和普通變量在一起說明int*pointer=1000;不要將一個整型量賦給一個指針變量存儲類型是指針變量本身的存儲類型數(shù)據(jù)類型說明指針所指向目標的數(shù)據(jù)類型指針的存儲類型和指針說明的程序位置決定了指針的壽命和可見性。即指針變量也分為內(nèi)部的和外部的,全局的和局部的。6.1.2指針變量的定義與初始化指針變量的初始化<存儲類型><數(shù)據(jù)類型>*指針名[=初始地址值];例如:charcc;char*pc=&cc;int*pointer=1000;intn;int*p=&n;int*q=p;#include<stdio.h>voidmain(){inta;
int*pa=&a;//指針pa指向a所在內(nèi)存地址a=10;printf("a:%d\n",a);printf("*pa:%d\n",*pa);printf("&a:0x%lx\n",&a);printf("pa:0x%lx)\n",pa);printf("&pa:%lx\n",&pa);}
運行結(jié)果:a:10*pa:10&a:0x1000fff4pa:0x1000fff4&pa:0x1000fff8void指針:<存儲類型>void*指針名;intx,*px=&x;void*pp;pp=px;可以將已定向的各種類型指針直接賦給void型指針int*px;void*pp=calloc(100);px=(int*)pp;必須采用強制類型轉(zhuǎn)換例:6.1.3指針的使用取地址運算符&例如&操作對象操作對象必須是左值表達式intx;chary;doublez;inta[4];registerintk;&x&y&z&a[2]&a&kint*char*double*int*錯誤錯誤單目&與操作對象組成地址表達式,運算結(jié)果為操作對象變量的地址,結(jié)果類型為操作對象類型的指針6.1.3指針的使用取內(nèi)容運算符*
例如*
操作對象操作對象必須是地址表達式,即指針(地址常量或指針變量)charc,*pc=&c;*(&c)='a′;*pc='a′;c='a′;注意區(qū)分*的不同含義:char*pc;抽象指針說明符a=a*10;乘運算符*pc=10;間訪運算符(單目*)運算結(jié)果為指針所指的對象,即變量本身(間接訪問表達式是左值表達式),結(jié)果類型為指針所指對象的類型。單目*和&的運算關(guān)系:單目*和&互為逆運算*(&左值表達式)=左值表達式&(*地址表達式)=地址表達式6.1.3指針的使用指針的正確用法(1)
必須按被引用變量的類型說明指針變量;(2)
必須用被引用變量的地址給指針變量賦值(或用指針變量初始化方式),使指針指向確定的目標對象,然后才能使用指針來引用變量。例:int*p;*p=5;NULL指針ANSIC++標準定義NULL指針,它作為指針變量的一個特殊狀態(tài),表示不指向任何東西使一個指針變量為NULL,可以給它賦一個零值測試一個指針變量是否為NULL,可以將它和零進行比較對一個NULL指針進行解引用操作是非法的6.1.3指針的使用例6.2
輸入a和b兩個整數(shù),按先大后小的順序來輸出a和b#include<stdio.h>voidmain(){int*p1,*p2,*p,a,ba=10;printf(“pleaseentertownumbers:”);scanf(“%d,%d”,&a,&b);p1=&a;p2=&b;if(a<b){p=p1;p1=p2;p2=p;}printf(“a=%d,b=%d\n”,a,b);printf(“max=%d,min=%d\n”,*p1,*p2);return0;}交換兩個指針變量的值實現(xiàn)a和b的交換輸出
運行結(jié)果:pleaseentertwonumbers:59a=5,b=9max=9,min=56.2指針運算指針的運算種類算術(shù)運算關(guān)系運算賦值運算6.2.1指針的算術(shù)運算指針可以進行的算術(shù)運算:p1+np1-np1++++p1p1—--p1p1-p2前提:指針是指向一片存儲單元(如數(shù)組)指針當前指向位置的前方或后方第n個數(shù)據(jù)的位置,位置的地址值是:(p)±n×sizeof(數(shù)據(jù)類型)(字節(jié))6.2.1指針的算術(shù)運算指針可以進行的算術(shù)運算:p1+np1-np1++++p1p1—--p1p1-p2指向下一個/上一個數(shù)據(jù)的位置,位置的地址值是:(p1)±sizeof(數(shù)據(jù)類型)(字節(jié))y=*px++;y=*(px++);y=++(*px);px的目標變量的值加一后賦予ypx的當前目標變量的值賦予y后,px加1指向下一個目標前提:指針是指向一片存儲單元(如數(shù)組)6.2.1指針的算術(shù)運算指針可以進行的算術(shù)運算有如下幾種p1+np1-np1++++p1p1—--p1p1-p2兩指針指向的地址位置之間的數(shù)據(jù)個數(shù):((p1)-(p2))/sizeof(數(shù)據(jù)類型)p1和p2指向同一組數(shù)據(jù)類型一致的數(shù)據(jù)inta[100],n;int*p1=a;*p2=&a[20];n=p2-p1;inta[100],b,n;int*p1=a;*p2=&b;n=p2-p1;前提:指針是指向一片存儲單元(如數(shù)組)6.2.1指針的算術(shù)運算例6.2
通過指針變量輸出a數(shù)組的5個元素intmain(){int*p,I,a[5];p=a;printf(“pleaseinput5numbers:\n”);for(i=0;i<5;i++)scanf(“%d”,p++);printf(“/n”);printf(“theinputarrayis:\n”);for(p=a,i=0;i<5;i++)printf(“%d”,*p++);return0;}
通過p獲得數(shù)組a各元素的地址
運行結(jié)果:pleaseinput5numbers:1234567890theinputarrayis:1234567890通過p訪問數(shù)組a各元素的值6.2.2指針的關(guān)系運算兩指針之間的關(guān)系運算表示它們指向的地址位置之間的關(guān)系。指向后方的指針大于指向前方的指針[存儲器的編號從小到大]p1<p2p1>p2p1==p2成立即p1指向位置在p2指向位置的前面成立即p1指向位置在p2指向位置的后面成立即p1和p2指向同一位置前提:兩個指針指向同一組類型相同的數(shù)據(jù)關(guān)系表達式的值為1:表達式成立0:表達式不成立變量的地址賦予一個指向相同數(shù)據(jù)類型的指針charc,*pc;pc=&c;一個指針的值賦予指向相同數(shù)據(jù)類型的另一個指針int*p,*q;p=q;數(shù)組的地址賦予指向相同數(shù)據(jù)類型的指針charname[20],*pname;pname=name;動態(tài)內(nèi)存分配int*p,n=20;p=(int*)malloc(n*sizeof(int));if(p!=NULL){…}6.2.3指針的賦值運算向指針變量賦值時,賦的值必須是地址常量或變量,不能是普通整數(shù)地址常量指針變量6.2.3指針的賦值運算動態(tài)內(nèi)存分配:在程序運行期間動態(tài)地分配存儲空間,分配的內(nèi)存空間放在數(shù)據(jù)區(qū)的堆(Heap)中動態(tài)內(nèi)存分配函數(shù):程序代碼區(qū)存放外部變量和靜態(tài)變量堆區(qū)存放自動變量和函數(shù)的形參數(shù)據(jù)區(qū)堆棧區(qū)靜態(tài)存儲區(qū)動態(tài)存儲區(qū)指定所分配內(nèi)存空間的大小if((指針名=(類型*)malloc(空間大小))==NULL){
出錯處理操作}malloc函數(shù)調(diào)用一般形式void*malloc(unsignedsize);原型函數(shù)在stdlib.h中,在使用它們的程序開頭處,必須寫有:#include <stdlib.h>函數(shù)運行成功,則返回值是大小為size的內(nèi)存空間首地址,否則,返回空指針。采用指針賦值操作把它的返回值通過類型強制轉(zhuǎn)換賦給一個指向相同數(shù)據(jù)類型的指針變量6.2.3指針的賦值運算接受malloc()函數(shù)在堆區(qū)中所分配的內(nèi)存空間首地址#include<stdio.h>#include<alloc.h>#include<stdlib.h>intmain(){inti=0,*a,N;printf(“Inputarraylength:”);scanf(“%d”,&N);a=(int*)malloc(N*sizeof(int));for(i=0;i<N;i++){a[i]=i+1;printf(“\n”);if((i+1)%10==0)printf(“\n”);}free(a);printf(“\n”);return0;}例6.4使用malloc和free函數(shù)的示例程序運行結(jié)果:Inputarraylength:15123456789101112131415voidfree(void*ptr);動態(tài)內(nèi)存釋放函數(shù):free()是malloc()的配對物,即在整個源程序內(nèi),它們是成對出現(xiàn)的6.3指針與數(shù)組6.3.1一維數(shù)組與指針數(shù)組與指針在訪問內(nèi)存時采用統(tǒng)一的地址計算方法,都可以處理內(nèi)存中連續(xù)存放的一系列數(shù)據(jù)一維數(shù)組與指針的關(guān)系inta[10];int*pa;pa=a;或pa=&a[0];*pa*(pa+1)a[1]a[0]*(pa+i)a[i]pa[i]*(a+i)6.3.1一維數(shù)組與指針#include<stdio.h>voidmain(){inti,*pa;inta[]={2,4,6,8,10};pa=a;
for(i=0;i<5;i++)printf(“a[%d]:%d”,i,pa[i]);
printf(”\n”);for(i=0;i<5;i++)printf(“*(pa+%d):%d”,i,*(a+i));printf(”\n”);}例6.4指針和數(shù)組表現(xiàn)形式互換性的程序運行結(jié)果:a[0]:2a[1]:4a[2]:6a[3]:8a[4]:10*(pa+0):2*(pa+1):4*(pa+2):6*(pa+3):8*(pa+4):10指針是地址變量,而數(shù)組名是地址常量pa=a;pa++,p??;pa+=n;a=pa;a++,a??;a+=n;指針指向數(shù)組的首地址指針采用數(shù)組的形式使用數(shù)組采用指針的形式使用6.3.1一維數(shù)組與指針#include<stdio.h>voidinvert(int*pdata,intn);//函數(shù)原型聲明voidmain(){inti;intdata[10]={1,80,2,5,8,12,45,56,9,6};
int*p=data; //定義指針變量pprintf("originalarray:\n");for(i=0;i<10;i++)
printf("%-4d",*(p+i));printf("\n");invert(p,10);
printf("invertedarray:\n");for(i=0;i<10;i++)
printf("%-4d",p[i]);}voidinvert(int*pdata,intn){inti,j,temp;for(i=0,j=n-1;i<j;i++,j--){temp=pdata[i];pdata[i]=pdata[j];pdata[j]=temp;}}例6.4將數(shù)組a中n個整數(shù)按相反的順序存放運行結(jié)果:originalarray:18025812455696invertedarray:69564512852801分析:將a[0]與a[n-1]對換,再將a[1]與a[n-2]對換,……直到將a[(n-1)/2]與a[n-int((n-1)/2)]對換調(diào)用函數(shù)(以指針作為實參)一維數(shù)組的信息一般要包含數(shù)組地址和元素個數(shù)兩個參數(shù)可替代為:voidinvert(intpdata[],intn)6.3.1一維數(shù)組與指針例6.9編寫三個函數(shù)分別完成指定一維數(shù)組元素的數(shù)據(jù)輸入、求一維數(shù)組的平均值、求一維數(shù)組的最大值和最小值。由主函數(shù)完成這些函數(shù)的調(diào)用。分析:采用地址傳遞的方式,把一維數(shù)組的存儲首地址作為實參數(shù)調(diào)用函數(shù)。在被調(diào)用的函數(shù)中,以一般(一級)指針變量作為形式參數(shù)接收數(shù)組的地址。該指針被賦予數(shù)組的地址之后,使用這個指針就可以對數(shù)組中的所有數(shù)據(jù)進行處理。函數(shù)原型:voidinput(float*,int);floataverage(float*,int);voidmaxmin(float*,int,float*,float*);float[]最大值和最小值需要返回,采用地址傳遞方式6.3.1一維數(shù)組與指針#include<stdio.h>voidinput(float*,int); floataverage(float*,int);voidmaxmin(float*,int,float*,float*); voidmain(){floatdata[10];//一維數(shù)組定義floataver,max,min;float*num=data;input(data,10);aver=average(data,10);
maxmin(num,10,&max,&min);printf("aver=%f\n",aver);//輸出平均值printf("max=%f,min=%f\n",max,min);}floataverage(float*pdata,intn)//數(shù)組平均值函數(shù){inti;floatavg;
for(avg=0,i=0;i<n;i++)avg+=pdata[i];
avg/=n;//求平均值
return(avg);//將平均值返回給被調(diào)用函數(shù)}函數(shù)原型聲明求最大值和最小值,以指針num以及max與min的地址作為函數(shù)實參voidinput(float*pdata,intn)//輸入數(shù)據(jù)函數(shù){inti;printf("pleaseinputarraydata:");for(i=0;i<n;i++)//逐個輸入數(shù)組的數(shù)據(jù) scanf(“%f”,pdata+i);scanf("%f",&pdata[i]);}voidmaxmin(float*pdata,intn,float*pmax,float*pmin){inti;*pmax=*pmin=pdata[0];
for(i=1;i<n;i++){if(*pmax<pdata[i])//求最大值*pmax=pdata[i];if(*pmin>pdata[i])//求最小值*pmin=pdata[i];}}例6.9編寫三個函數(shù)分別完成指定一維數(shù)組元素的數(shù)據(jù)輸入、求一維數(shù)組的平均值、求一維數(shù)組的最大值和最小值。由主函數(shù)完成這些函數(shù)的調(diào)用。指針形式數(shù)組形式6.3.2多維數(shù)組與指針多維數(shù)組的地址:C語言中,數(shù)組在實現(xiàn)方法上只有一維的概念,多維數(shù)組被看成以下一級數(shù)組為元素的一維數(shù)組(1)n維數(shù)組(n≥2)可以逐級分解為n-1維數(shù)組為元素的一維數(shù)組;(2)n維數(shù)組的數(shù)組名是指向n-1維數(shù)組的指針,其值為n維數(shù)組的首地址,類型為n-1維數(shù)組類型的指針。(3)n維數(shù)組的元素是指向n-1維數(shù)組的元素的指針,其值為n-1維數(shù)組的首地址,類型為n-1維數(shù)組的元素類型的指針;6.3.2多維數(shù)組與指針多維數(shù)組的地址:intdata[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};datadata[0]data[1]data[2]data+1data+2data第一級分解,數(shù)組data被看成長度為3的一維數(shù)組第二級分解,data[0],data[1],data[2]又是三個長度為4的一維數(shù)組6.3.2多維數(shù)組與指針數(shù)組指針:<存儲類型><數(shù)據(jù)類型>(*數(shù)組指針名)[元素個數(shù)];數(shù)組指針的一般定義格式為:數(shù)組指針的(物理)地址增量值以N-1維數(shù)組的長度為單位如何用單個指針變量處理多維數(shù)組?單個指針變量可處理一維數(shù)組N維數(shù)組是以N-1維數(shù)組為元素的一維數(shù)組以N-1維數(shù)組為數(shù)據(jù)類型定義指針變量,則可處理以N-1維數(shù)組為元素的一維數(shù)組6.3.2多維數(shù)組與指針數(shù)組指針:(1)不能把一個一維數(shù)組的首地址,即一維數(shù)組名直接賦給指向相同數(shù)據(jù)類型的數(shù)組指針,如:
inta[10],(*ap)[10];
ap=a;//錯誤ap=(int(*)[10])a;//正確或者用初始化操作寫成:
inta[10],(*ap)[10]=(int(*)[10])a;(2)數(shù)組指針指向了一維數(shù)組a,也不能用“ap[i]”或“*ap[i]”等形式的表達式訪問一維數(shù)組a的第i號元素。
類型不一致,a的類型為int*,ap的類型為int(*)[10]。強制類型轉(zhuǎn)換(*ap)=a(*ap)+i=a+i(*ap)[i]=*((*ap)+i)=a[i]=*(a+i)6.3.2多維數(shù)組與指針例6.10用數(shù)組指針指向一維數(shù)組#include<stdio.h>voidmain(){inti;inta[4],(*ap)[4];//定義數(shù)組指針apap=(int(*)[4])a;//給數(shù)組指針ap定向,指向一維數(shù)組a//借助數(shù)組指針ap的地址計算公式,用鍵盤給一維數(shù)組a的每個元素賦值for(i=0;i<4;i++){printf("第[%d]號元素:",i);scanf("%d",*ap+i);}//由數(shù)組指針ap的地址計算公式讀取一維數(shù)組a的元素值顯示在CRT上for(i=0;i<4;i++)printf("%d\t",*(*ap+i));printf("\n");}例6.11輸出二維數(shù)組任意元素#include<stdio.h>voidmain(){ inta[3][4]={1,2,3,4,5,6,7,8,9,10,11,12}; //定義二維數(shù)組a并且初始化
int(*ap)[4],i,j; //定義包含4個元素的一維數(shù)組指針apap=a; //ap指向二維數(shù)組a的第0行
printf(“pleaseenterrowandcolumnnumber:”);scanf(“%d%d”,&i,&j);//鍵入元素行列號
printf("a(%d,%d)=%d:\n",i,j,*(*(ap+i)+j));}6.3.2多維數(shù)組與指針多維數(shù)組與指針的應(yīng)用:多維數(shù)組可以看成是特殊的一維數(shù)組,當需要在函數(shù)之間進行多維數(shù)組的傳遞時,可以將多維數(shù)組進行降維處理,使之變?yōu)橐痪S數(shù)組然后對降維后的一維數(shù)組進行相應(yīng)的處理。例6.10有一個班,3個學(xué)生,各學(xué)4門功課,計算總平均成績和第二個學(xué)生的平均成績#include<stdio.h>floataver(float*,intn);//原型聲明voidmain(){floatscore[3][4]={{63,65,75,61},{83,87,90,85},
{90,95,100,93}};
printf("totalaveragescore=%f\n",aver(*score,12));printf("secondstudentaveragescore=%f",aver(score[1],4));}floataver(float*pdata,intn){inti;floataverage=0;//初始化為零
for(i=0;i<n;i++)average+=pdata[i];//累加和
average=average/n;//求平均值
returnaverage;//將平均值返回
}行首地址作為實參6.3.2多維數(shù)組與指針例6.10求4×3的矩陣中元素的最大值#include<stdio.h>intmax(intarray[][3],intn);//函數(shù)聲明intmain(){inta[4][3]={{1,2,3},{4,5,6},{3,6,8},{7,12,11}};
printf(”Maxvalueis%d\n”,max(a,4));
return0;}intmax(intarray[][3],intn){inti,j,max;max=array[0][0];for(i=0;i<3;i++)for(j=0;j<n;j++)if(array[i][j]>max)max=array[i][j];return(max);}二維數(shù)組名a作為實參形參實質(zhì)為數(shù)組指針形式6.3.2多維數(shù)組與指針例6.10有一個班,3個學(xué)生,各學(xué)4門功課,編程實現(xiàn)分別顯示每個學(xué)生有幾門課程是優(yōu)秀的(90分以上為優(yōu)秀)以及每個學(xué)生的成績voidsearch(int(*p)[4],intn){inti,j,k,flag_f;for(i=0;i<n;i++){k=0;flag_f=0;//flag_f用來存放優(yōu)秀的成績數(shù)
do{for(j=k;j<4;j++){if(p[i][j]>90){flag_f++;break;
}}
k=j+1;//k存儲上次查詢完之后的一個數(shù)的列數(shù)
}while(j<4);
printf(“No.%dhas%dgradeexcellently,hisscore\
are:\n”,i+1,flag_f);for(j=0;j<4;j++)printf("%-4d",p[i][j]);printf("\n");}}#include<stdio.h>voidsearch(int(*p)[4],intn);//原型聲明voidmain(){//二維數(shù)組定義及初始化
intscore[3][4]={{93,96,44,61},\
{83,87,90,45},\
{58,95,26,59}};search(score,3);//尋找滿足要求的學(xué)生}運行結(jié)果:No.1has2gradeexcellently,hisscoreare:93964461No.2has1gradeexcellently,hisscoreare:83879045No.3has1gradeexcellently,hisscoreare:58952659voidsearch(intp[][4],intn)有優(yōu)秀成績時,計數(shù)器加1并退出里層循環(huán)數(shù)組形式6.4指針數(shù)組和多級指針6.4.1指針數(shù)組:指針的集合,它的每一個元素都是一個指針變量,并且它們具有相同的存儲類型和指向相同的數(shù)據(jù)類型。指針數(shù)組的定義:<存儲類型><數(shù)據(jù)類型>*指針數(shù)組名[元素個數(shù)];int*p[2];指針數(shù)組可以用來處理多維數(shù)組intdata[2][3];int*pdata[2];pdata[0]=data[0];或pdata[0]=&data[0][0];pdata[1]=data[1];或pdata[1]=&data[1][0];6.4.1指針數(shù)組例6.15用指針數(shù)組處理二維數(shù)組的數(shù)據(jù)#include<stdio.h>main(){intdata[2][3],*pdata[2];inti,j;for(i=0;i<2;i++)//二維數(shù)組賦值
for(j=0;j<3;j++)data[i][j]=(i+1)*(j+1);pdata[0]=data[0];//將指針數(shù)組的各個元素指向降維后的一維數(shù)組
pdata[1]=data[1];for(i=0;i<2;i++)for(j=0;j<3;j++,pdata[i]++)//采用指針數(shù)組輸出數(shù)組內(nèi)容
printf(”data[%d][%d]:%-2d\n”,i,j,*pdata[i]);}運行結(jié)果:data[0][0]:1data[0][1]:2data[0][2]:3data[1][0]:2data[1][1]:4data[1][2]:6data[i][j]和*(data[i]+j),*(pdata[i]+j)和pdata[i][j]是意義相同的表示方法6.4.1指針數(shù)組例6.15指針數(shù)組和數(shù)組指針分別處理二維數(shù)組#include<stdio.h>voidoutput1(int**app,intn);voidoutput2(int(*bpp)[3],intn);voidmain(){int*ap[5];int(*bp)[3];inti,j;intarr[5][3]={{1,2,3},{4,5,6},{7,8,9},{10,11,12},{13,14,15}};for(i=0;i<5;i++)ap[i]=arr[i];bp=arr;output1(ap,5);//以指針數(shù)組名作為實參
output2(bp,5);//以數(shù)組指針名作為實參}voidoutput1(int*app[],intn){inti,j;printf("thearrayis:\n");for(i=0;i<n;i++){for(j=0;j<3;j++)printf("%-5d",*(*(app+i)+j));printf("\n");}}voidoutput2(int(*bpp)[3],intn){inti,j;printf("thearrayis:\n");for(i=0;i<n;i++){for(j=0;j<3;j++)printf("%-5d",*(*(bpp+i)+j));printf("\n");}}運行結(jié)果:thearrayis:123456789101112131415thearrayis:123456789101112131415數(shù)組指針指向二維數(shù)組二級指針作為形參接收指針數(shù)組數(shù)組指針作為形參處理二維數(shù)組6.4.2多級指針一個指針變量指向的變量仍然是一個指針變量,就構(gòu)成指向指針變量的指針變量,簡稱指向指針的指針或二級指針二級指針的聲明形式:
int**ap;int*s;intnum;ap=&s;s=#num=100;目標變量的數(shù)據(jù)類型存儲類型
數(shù)據(jù)類型**指針名;*ap是取ap中的內(nèi)容,得到一個指針值即s中的內(nèi)容**ap即“*(*ap)”,再取上述“*ap”的內(nèi)容,得到num的值num=100;
*s=100;
**ap=100;6.4.2多級指針程序中經(jīng)常使用二級指針來處理指針數(shù)組intarr[3][4]={{1,2,3,4},{4,5,6,7},{7,8,9,10}};int*num[3];for(i=0;i<3;i++)
num[i]=arr[i];pp指向指針數(shù)組num[]。pp的目標變量*pp就是num[0],*(pp+1)就是num[1],*(pp+2)就是num[2]。pp就是指向指針型數(shù)據(jù)的指針變量6.4.2多級指針例6.18多級指針處理二維數(shù)組#include<stdio.h>intmain(){intnum[3][4]={{0,1,2,3},{1,2,3,4},{2,3,4,5}};int*p[3],**pp;inti,j;for(i=0;i<3;i++)p[i]=num[i];pp=p; //使二級指針p指向指針數(shù)組p的首地址for(i=0;i<3;i++){for(j=0;j<4;j++)printf(“%-3d”,*(*(pp+i)+j));
printf(“\n”);}}運行結(jié)果:012312342345借助二級指針輸出數(shù)組元素*(*(pp+i)+j),*(p[i]+j),p[i][j],*(*(num+i)+j),*(num[i]+j),num[i][j]表達形式等價指針數(shù)組p存放數(shù)組num每行的首地址6.4.2多級指針例6.18多級指針處理二維數(shù)組#include<stdio.h>voidoutput(int**p,intn1,intn2);intmain(){intnum[3][4]={{0,1,2,3},{1,2,3,4},{2,3,4,5}};int*p[3],**pp;for(i=0;i<3;i++)p[i]=num[i];
pp=p; output(pp,3,4);//調(diào)用函數(shù)}voidoutput(int**p,intn1,intn2);//n1,n2為二級指針指向的數(shù)組行列數(shù){inti,j;for(i=0;i<n1;i++){for(j=0;j<n2;j++)printf(“%-3d”,*(*(pp+i)+j));
printf(“\n”);}}二級指針變量作為函數(shù)形參6.5指針與函數(shù)6.5.1返回指針的函數(shù):當函數(shù)的返回值是地址時,該函數(shù)就是指針型函數(shù)。<存儲類型><數(shù)據(jù)類型>*函數(shù)名(函數(shù)的形式參數(shù)及說明);該函數(shù)本身的存儲特性,分外部型或static型返回值地址所在的內(nèi)存空間中存儲數(shù)據(jù)的數(shù)據(jù)類型函數(shù)體內(nèi)必須有return語句,其后跟隨的表達式結(jié)果值可以是變量的地址、數(shù)組首地址、已經(jīng)定向的指針變量、結(jié)構(gòu)變量地址、結(jié)構(gòu)數(shù)組的首地址等這些變量和數(shù)組須是全局或靜態(tài)型,不能把被調(diào)用函數(shù)內(nèi)的自動變量的地址和自動型數(shù)組的首地址作為指針函數(shù)的返回值6.5.1返回指針的函數(shù)例6.20求平方(錯誤例)#include<stdio.h>double*square(double);intmain(){doublenum=5.0;double*ptr=0;ptr=square(num);printf("Num'ssquare=%f\n",num*num);printf("Result=%f\n",*ptr);return0;}
double*square(doubledata){doubleresult=0.0;result=data*data;return&result;}永遠不要從函數(shù)中返回局部自動變量的地址運行結(jié)果:Num'ssquare=25.000000Result=6.122651851057717610000000000000000000000e+2126.5.1返回指針的函數(shù)例6.21模擬成績檢索系統(tǒng),對學(xué)生成績進行搜索,找出其中有不及格分數(shù)的學(xué)生學(xué)號和不及格課程號及分數(shù)。學(xué)生的成績按照百分制進行記錄,學(xué)生的學(xué)號為(1-10),課程編號為(1-4)。問題分析與設(shè)計:
數(shù)據(jù)結(jié)構(gòu):建立學(xué)生成績10*4二維數(shù)組,行代表不同學(xué)號,列代表不同課程。函數(shù)原型:
完成一行數(shù)據(jù)的搜索,搜索到不及格分數(shù)時,終止搜索,返回不及格分數(shù)的存儲地址,以及其在數(shù)組中的列號
int*search(int(*pointer)[4],int*pm);返回不及格分數(shù)的存儲地址該不及格分數(shù)在數(shù)組中的列號6.5.1返回指針的函數(shù)#include<stdio.h>/*聲明查找函數(shù)*/int*search(int(*pointer)[4],int*pm);intmain(){intscore[10][4]={{67,68,78,88},{90,69,66,79},{67,70,89,85},{65,76,69,70},{78,87,83,79},{88,70,48,57},{80,63,90,84},{67,48,70,84},{92,90,77,70},{87,88,69,84}};int*pt_1;introw,column=0;int*pm_1=&column;for(row=0;row<10;row++){pt_1=search(score+row,pm_1);if(pt_1!=NULL)//出現(xiàn)不及格
{printf("Stu[%d]'sNo.%dcourse'sscoreis:",row+1,column);printf("%d\n",*pt_1);row--; //該行未掃描完,應(yīng)繼續(xù)掃描剩下列
}else*pm_1=0; //表示該行已掃描完
}}/*定義查找函數(shù)*//*入口參數(shù)中:(*pointer)[4]是所查找的一行,*pm用于存放列地址*/int*search(int(*pointer)[4],int*pm){inti;int*pt;pt=NULL;/*采用*pm間接傳遞了掃描列初址,當該生有多科不及格時為上次掃描之后一列*/for(i=*pm;i<4;i++) { if(*(*pointer+i)<60){pt=*pointer+i;*pm=(i+1);break;}}returnpt;}運行結(jié)果:Stu[6]'sNo.3course'sscoreis:48Stu[6]'sNo.4course'sscoreis:57Stu[8]'sNo.2course'sscoreis:48逐行掃描的基礎(chǔ)上,當發(fā)現(xiàn)又不及格現(xiàn)象的時候,轉(zhuǎn)為逐個掃描數(shù)組指針傳遞二維數(shù)組6.5.2指向函數(shù)的指針在C語言中,函數(shù)整體不能作為參數(shù)直接傳遞給另一個函數(shù)。盡管函數(shù)不是變量,但它卻具有內(nèi)存物理地址。函數(shù)的函數(shù)名和數(shù)組相似,函數(shù)名表示該函數(shù)有存儲首地址,即函數(shù)的執(zhí)行入口地址。
函數(shù)指針:存儲函數(shù)的入口地址,可以通過該指針變量來調(diào)用它所指的函數(shù)。其定義格式<存儲類型><數(shù)據(jù)類型>(*函數(shù)指針名)(參數(shù)表)[=函數(shù)名];函數(shù)指針本身的存儲類型,有auto型、static型和extern型指針所指函數(shù)返回值的數(shù)據(jù)類型floatadd(floata,floatb);float(*pfun)(float
,float);pfun=add;或float(*pfun)(float,float)=add;函數(shù)指針進行定向操作的兩種方式先定義后用地址賦值語句初始化操作定義一個函數(shù)指針時,至少應(yīng)指明參數(shù)表內(nèi)的參數(shù)個數(shù)和各參數(shù)的數(shù)據(jù)類型函數(shù)和指向它的函數(shù)指針應(yīng)具有相同的數(shù)據(jù)類型,否則,應(yīng)該采用強制類型轉(zhuǎn)換,兩者的形參表必須完全相同6.5.2指向函數(shù)的指針數(shù)據(jù)指針的取內(nèi)容運算表達式“*數(shù)據(jù)指針名”,是訪問該指針所指的數(shù)據(jù),而函數(shù)指針的取內(nèi)容運算表達式“*函數(shù)指針名”,是使程序控制轉(zhuǎn)移到函數(shù)指針所指的函數(shù)目標代碼模塊首地址,執(zhí)行該函數(shù)的函數(shù)體目標代碼。函數(shù)指針與數(shù)據(jù)指針的不同數(shù)據(jù)指針指向數(shù)據(jù)區(qū),而函數(shù)指針指向程序代碼區(qū)函數(shù)指針代替函數(shù)名的調(diào)用語句一般格式:(*函數(shù)指針名)(參數(shù)表);①函數(shù)指針名(參數(shù)表);②在實際應(yīng)用中,在一個執(zhí)行過程中可以調(diào)用不同函數(shù)時,函數(shù)的傳遞能體現(xiàn)出較大的優(yōu)越性。floatc;c=pfun(3.5,6.2);c=(*pfun)(3.5,6.2);6.5.2指向函數(shù)的指針例6.22編寫函數(shù)實現(xiàn)積分#include<stdio.h>#include<math.h>floatintegrate(floata,floatb,intn,float(*f)(float));floatsin2(floatx);floatf1(floatx);/*積分函數(shù)定義*//*a,b為積分邊界,n為積分區(qū)間分割數(shù),f指向被積分函數(shù)*/floatintegrate(floata,floatb,intn,float(*f)(float)){floats,d;inti;d=(b-a)/n; //微元精度ds=(*f)(a)*d; //微元面積
for(i=1;i<=n-1;i++)s=s+(*f)(a+i*d)*d;//微元面積相加
returns;}/定義被積函數(shù)*/floatsin2(floatx){returnsin(x)*sin(x);}floatf1(floatx){returnx*x+x/2;}
intmain(){//定義指針指向函數(shù)sin2float(*p)(float)=sin2; printf("%f",integrate(0,1,100,p));printf("%f",integrate(-1,2,100,f1));return0;}函數(shù)指針變量作為實參函數(shù)名作為實參運行結(jié)果:0.2691433.6829506.5.2指向函數(shù)的指針例6.24計算從2015年開始某年母親節(jié)(5月第2個周日)的具體日期問題分析與設(shè)計:
設(shè)計思路:首先通過輸入獲得母親節(jié)的周數(shù)(2)和星期數(shù)(7),以及需要查詢的年份,然后調(diào)用日期獲取函數(shù)(指針函數(shù))得到基準年(2015年)的母親節(jié)是5月10日,然后由指針指向閏年判斷函數(shù)(函數(shù)指針)得到邏輯值來進行日期演算,從而得到當年母親節(jié)的日期
數(shù)據(jù)結(jié)構(gòu):寫出2015年5月的日期編號,建立基準二維數(shù)組。函數(shù)原型:int*GetDate(int(*p)[7],intwk,intdy);intLeap_Year_Judge(inty);6.5.2指向函數(shù)的指針#include<stdio.h>int*GetDate(int(*p)[7],intwk,intdy);intLeap_Year_Judge(inty);voidmain(){intMay_2015[6][7]={{-1,-1,-1,-1,1,2,3},{4,5,6,7,8,9,10},{11,12,13,14,15,16,17},{18,19,20,21,22,23,24},{25,26,27,28,29,30,31},{-1,-1,-1,-1,-1,-1,-1}};intyr,wk,dy,i,date,temp;int(*ad)(int);do{printf("Enterweek(1-6)andday(1-7):");scanf("%d%d\n",&wk,&dy);printf("Enteryear(>=2015):");scanf("%d\n",&yr);}while(wk<1||wk>6||dy<1||dy>7||\(*GetDate(May_2015,wk,dy)==-1));date=*GetDate(May_2015,wk,dy);
ad=Leap_Year_Judge(yr);for(i=2016;i<=yr;i++){if((*ad)(i)==0)temp=1;
if((*ad)(i)==1)temp=2;
date-=temp;if(date<=7)date+=7;//取得第i年母親節(jié)的date}printf("the%dmother'sdayisMay%dst\n",\yr,date);}/*日期地址獲取函數(shù)*/int*GetDate(int(*p)[7],intwk,intdy){return&p[wk-1][dy-1];}intLeap_Year_Judge(inty){if((y%4==0&&y%100!=0)||(y%400==0))return1;elsereturn0;}運行結(jié)果:Enterweek(1-6)andday(1-7):27Enteryear(>=2015):2017the2017mother'sdayisMay14st6.6綜合應(yīng)用例6.25 編寫程序,用指針形式訪問數(shù)組元素,實現(xiàn)矩陣轉(zhuǎn)置功能問題分析與設(shè)計:
模塊劃分:矩陣轉(zhuǎn)置功能塊:完成矩陣的轉(zhuǎn)置。
數(shù)據(jù)結(jié)構(gòu):采用數(shù)組指針,以地址傳遞方式實現(xiàn)函數(shù)間二維數(shù)組(矩陣)傳遞。函數(shù)原型:voidconvert(int(*a)[],int(*at)[],introw,intcol);功能:矩陣的轉(zhuǎn)置形參:數(shù)組指針a傳遞轉(zhuǎn)置前的矩陣,數(shù)組指針at返回轉(zhuǎn)置后的矩陣數(shù)據(jù)row和col分別為矩陣的行列數(shù)
#include<stdio.h>#defineN13 #defineN24voidconvert(int(*)[],int(*)[],int,int);
intmain(){intarr1[N1][N2]={1,2,3,4,5,6,7,8,9,10,11,12};
intarr2[N2][N1];
int(*p)[N2], (*pt)[N1];
inti,j;p=arr1; pt=arr2;convert(p,pt,N1,N2);printf("thenewarrayis:\n");for(i=0;i<N2;i++)
{for(j=0;j<N1;j++)printf("%-4d",*(*(pt+i)+j));printf("\n");}printf("thenewarrayis:\n");for(i=0;i<N2;i++)
{for(j=0;j<N1;j++)printf("%-4d",arr2[i][j]);printf("\n");}}6.6綜合舉例宏定義行列大小函數(shù)聲明函數(shù)調(diào)用采用指針方法輸出轉(zhuǎn)置后的目標矩陣定義數(shù)組指針采用數(shù)組方法輸出/**轉(zhuǎn)置函數(shù)convert()**指針數(shù)組a和at指向轉(zhuǎn)置前后的矩陣**row和col為轉(zhuǎn)置前矩陣的行列值**/voidconvert(int(*a)[N2],int(*at)[N1],introw,intcol) {inti,j;for(i=0;i<row;i++)for(j=0;j<col;j++)*(*(at+j)+i)=*(*(a+i)+j);}運行結(jié)果:thenewarrayis:1592610371148126.6綜合應(yīng)用例6.26 編寫程序,對整型數(shù)組進行排序(冒泡法)問題分析與設(shè)計:
設(shè)計思路:定義函數(shù)指針以方便調(diào)用升降序邏輯函數(shù),從而實現(xiàn)升序或降序的排序功能。
數(shù)據(jù)結(jié)構(gòu):采用一維數(shù)組存儲待排序的數(shù)據(jù),以地址傳遞方式實現(xiàn)函數(shù)間數(shù)組傳遞。函數(shù)原型:(1)intascending(inta,intb);功能:升序邏輯判斷形參:a,b為待比較的兩個整數(shù)返回:若a>b,值為1,否則,值為06.6綜合應(yīng)用(2)intdescending(inta,intb);功能:降序邏輯判斷形參:a,b為待比較的兩個整數(shù)返回:若a<b,值為1,否則,值為0(3)voidexchange(int*a,int*b);功能:兩個整數(shù)的交換形參:a,b為待交換的兩個整數(shù)存儲地址,通過地址傳遞方式,實現(xiàn)實參的交換返回:無(4)voidsort(inta[],intn,intflag);功能:按給定的升序或降序完成一維數(shù)組的排序形參:a[]為指向待排序數(shù)組的指針,采用地址傳遞方式n為數(shù)組的長度flag為升降序標志返回:無#include<stdio.h>#defineFALSE0#defineTRUE!0/*******************************/intascending(int,int); intdescending(int,int);voidexchange(int*,int*);voidsort(int[],int,int); intmain(){intnum[10]={1,5,9,2,6,10,3,4,7,8};
intflag1; //升降序標志符
inti;scanf("%d",&flag1);sort(num,10,flag1);printf("sortedarrayis:");
for(
溫馨提示
- 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)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2024年度天津市公共營養(yǎng)師之二級營養(yǎng)師自我提分評估(附答案)
- 2024年度四川省公共營養(yǎng)師之四級營養(yǎng)師模考預(yù)測題庫(奪冠系列)
- 生態(tài)養(yǎng)老休閑度假區(qū)新建項目可行性方案研究報告
- 2025上海市農(nóng)作物種苗買賣合同模板
- 中國利樂枕項目投資可行性研究報告
- 五層瓦楞紙項目可行性研究報告
- 2025年中國信插行業(yè)發(fā)展前景預(yù)測及投資戰(zhàn)略研究報告
- 2025年中國貴州旅游行業(yè)發(fā)展運行現(xiàn)狀及投資戰(zhàn)略規(guī)劃報告
- 2025年胃膜素項目可行性研究報告
- 車型內(nèi)胎項目可行性研究報告
- ISO 56001-2024《創(chuàng)新管理體系-要求》專業(yè)解讀與應(yīng)用實踐指導(dǎo)材料之4:4組織環(huán)境-4.2理解相關(guān)方的需求和期望(雷澤佳編制-2025B0)
- 2024年一級支行行長競聘演講稿例文(4篇)
- 健身房銷售人員培訓(xùn)
- 建筑工程施工合同:游泳館建設(shè)
- 中建中建機械頂管專項方案范本
- 2024-2025學(xué)年 數(shù)學(xué)二年級上冊冀教版期末測試卷(含答案)
- 2024年1月遼寧省普通高中學(xué)業(yè)水平合格性考試物理試題(含答案解析)
- 期末測試卷(試題)-2024-2025學(xué)年四年級上冊數(shù)學(xué)滬教版
- 小沈陽《新上海灘》經(jīng)典臺詞
- 建工會職工之家的申請.doc
- CSFB信令流程(常用)
評論
0/150
提交評論