版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
高級語言程序設(shè)計高級語言程序設(shè)計——基于計算思維能力培養(yǎng)高級語言程序設(shè)計——基于計算思維能力培養(yǎng)第7章指針及其應(yīng)用主要內(nèi)容指針變量的定義與初始化間接尋址運算符指針與函數(shù)指針與一維數(shù)組字符指針、指針與二維數(shù)組本章思維導(dǎo)圖
指針的本質(zhì)7.17.1指針的本質(zhì)00000001…5000500150025003inta;&a指針的本質(zhì)就是內(nèi)存地址。CPU指令CPU訪問內(nèi)存:直接尋址方式和間接尋址方式。7.1指針的本質(zhì)00000001…5000500150025003&ascanf("%d",&a);inta;直接尋址方式7.1指針的本質(zhì)5000500150025003scanf("%d",p);inta;間接尋址方式變量p5000保存a地址用于保存變量地址的變量稱為指針變量!7.1指針的本質(zhì)
在本書中,若指針變量p保存了變量a的地址,我們說“p指向a”。pa
今后,我們把指針指向的變量統(tǒng)稱為指針變量指向的對象,簡稱指針指向的對象。7.1指針的本質(zhì)指針變量的
定義與初始化7.2
1、指針變量的定義語法:基類型*指針變量名inta,*p;charc,*q;定義了整型變量a和整型
指針變量p定義了字符變量c和字符
指針變量q該指針變量只能保存類型為基類型的變量地址
同時定義多個同類型的指針變量時,需要在每個指針變量的名稱前加*。float*ptr1,*ptr2;定義了兩個基類型為float的指針變量。float*ptr1,ptr2;ptr1為指針變量ptr2為float變量1、指針變量的定義未初始化或賦值的指針變量值是不確定的!
可以在定義指針變量時進(jìn)行初始化例如: inta,*p=&a;//把整型變量a的地址賦值給p(1)初始化指向一個具體的變量。2、指針變量的初始化未初始化或賦值的指針變量值是不確定的!
也可以先定義指針變量,再使用賦值語句給指針賦初值,例如: inta,*p; p=&a; //將變量a的地址存入變量p注意:p之前不要加*號(1)初始化指向一個具體的變量。2、指針變量的初始化此時:scanf(“%d”,&a);與scanf("%d",p);的作用是相同的,都是將鍵盤輸入的數(shù)據(jù)存入到變量a。pa2、指針變量的初始化
請注意區(qū)分scanf(“%d”,p)與scanf(“%d”,&p)的區(qū)別。pa2、指針變量的初始化可以用格式控制符%p以十六進(jìn)制無符號的形式輸出內(nèi)存的地址或指針變量的內(nèi)容。例如,若p指向a時,可用以下語句輸出a的地址和指針變量p的值:printf("&a=%p,p=%p\n",&a,p);2、指針變量的初始化【例7.1】使用指針變量顯示變量的地址#include<stdio.h>intmain(){chara,*p;intb,*q;p=&a; //p指向aq=&b; //q指向bprintf("&a=%p,&a=%p,&p=%p\n",&a,p,&p);printf("&b=%p,&b=%p,&q=%p\n",&b,q,&q);【例7.1】使用指針變量顯示變量的地址printf("sizeof(p)=%d\n",sizeof(p));
//輸出char型指針變量占用的字節(jié)數(shù)printf("sizeof(q)=%d\n",sizeof(int*));
//輸出int型指針變量占用的字節(jié)數(shù)return0;}&a=0022FF1F,&a=0022FF1F,&p=0022FF18&b=0022FF14,&b=0022FF14,&q=0022FF10sizeof(p)=4sizeof(q)=4變量地址依賴于具體的機器不同而不同(2)將指針變量初始化為空指針。int*p=NULL;之后可通過if(p!=NULL)來判斷p是否指向了有效變量,以確定可否訪問p指向的對象。NULL為stdio.h中定義的常量#defineNULL02、指針變量的初始化
注意不能直接將除NULL之外的整數(shù)賦值給指針變量。例如:int*p=100;是不允許的。這是因為內(nèi)存地址為100的單元未經(jīng)操作系統(tǒng)分配,可導(dǎo)致通過p非法訪問該內(nèi)存的錯誤。
2、指針變量的初始化1.以下選項正確的是()。int*a=200,*b=a;inta;char*p=&a;inta=200,*p=NULL;doublex,y,*p=&x,*q=y;ABCD提交單選題5分間接尋址運算符7.37.3間接尋址運算符C語言通過間接尋址運算符*來訪問指針指向的對象。其格式為:
*指針
例如,當(dāng)指針p保存了a的地址時,*p代表其指向的對象,此時*p==a。pa*p#include<stdio.h>intmain(){inta=10,*p=&a; //將指針變量p初始化為&aprintf("&a=%p,&a=%p,&p=%p\n",&a,p,&p);printf("a=%d,*p=%d\n",a,*p);*p=*p+10; //等價于a=a+10;printf("a=%d,*p=%d\n",a,*p);printf("*&a=%d\n",*&a);return0;} 【例7.2】利用指針間接訪問變量示例。&a=0022FF1C,&a=0022FF1C,&p=0022FF18a=10,*p=10a=20,*p=20*&a=20*p=*p+10;注意:*&a等價為a
指針與函數(shù)7.4值傳遞時,實參與形參分別占用不同的存儲單元,在函數(shù)內(nèi)改變形參的值不會影響實參的值。單向值傳遞7.4.1傳值調(diào)用與傳地址調(diào)用voidswap(inta,intb){ inttemp; temp=a; a=b; b=temp;}intmain(){ inta,b; a=10;b=20; swap(a,b); printf(“a=%d,b=%d”,a,b);}程序的輸出結(jié)果為:a=10,b=207.4.1傳值調(diào)用與傳地址調(diào)用a10單向值傳遞演示b20main函數(shù)swap函數(shù)tempa10b2010swap(a,b);a20b20main函數(shù)swap函數(shù)tempa10b2010swap(a,b);單向值傳遞演示a20b10main函數(shù)swap函數(shù)tempa10b2010swap(a,b);單向值傳遞演示按地址調(diào)用函數(shù)的形參為指針變量函數(shù)實參為主調(diào)函數(shù)中變量的地址函數(shù)調(diào)用時,實參值賦值給形參形參變量獲得主調(diào)函數(shù)中變量的地址后,就可在被調(diào)函數(shù)中通過形參來間接訪問其指向的對象,從而達(dá)到修改主調(diào)函數(shù)中變量的目的。按地址調(diào)用#include<stdio.h>voidchange(int*p){printf("*p=%d\n",*p);
*p=0;printf("*p=%d\n",*p);}intmain(){intx=10;printf("x=%d\n",x);change(&x); printf("x=%d\n",x);return0;}x=10*p=10*p=0x=07.4.2指針作函數(shù)參數(shù)的應(yīng)用實例傳地址函數(shù)調(diào)用方式為我們提供了修改主調(diào)函數(shù)中局部變量的可能。相應(yīng)地,設(shè)計函數(shù)時應(yīng)該
采用指針作函數(shù)參數(shù)。指針作為函數(shù)參數(shù):(1)希望通過函數(shù)調(diào)用來修改主調(diào)函數(shù)中的局部變量。(2)被調(diào)函數(shù)需要向主調(diào)函數(shù)返回多個值。7.4.2指針作函數(shù)參數(shù)的應(yīng)用實例【例7.4】編寫函數(shù)swap,實現(xiàn)兩個整數(shù)的交換。#include<stdio.h>voidswap(int*p,int*q){inttemp;//此處temp為整型變量temp=*p;
*p=*q;
*q=temp;}intmain(){inta=10,b=20;printf("a=%d,b=%d\n",a,b);swap(&a,&b); //實參為a與b的地址printf("a=%d,b=%d\n",a,b);return0;}p&a傳地址調(diào)用演示q&bmain函數(shù)swap函數(shù)tempa10&a&bb20swap(&a,&b);p&aq&bmain函數(shù)swap函數(shù)tempa10b2010swap(&a,&b);*p*q傳地址調(diào)用演示p&aq&bmain函數(shù)swap函數(shù)tempa20b2010swap(&a,&b);*p*q傳地址調(diào)用演示p&aq&bmain函數(shù)swap函數(shù)tempa20b1010swap(&a,&b);*p*q傳地址調(diào)用演示(1)voidswap(int*p,int*q){ int*temp; //此處temp為整型指針變量 temp=p; p=q; q=temp;}該程序的功能是什么?(2)voidswap(int*p,int*q){ int*temp; //此處temp為整型指針變量 *temp=*p; *p=*q; *q=*temp;}該程序有何問題?2.以下程序段完全正確的是()。int*p;scanf("%d",&p);int*p;scanf("%d",p);intk,*p=&k;scanf("%d",p);intk,*p;*p=&k;scanf("%d",p);ABCD提交單選題5分3.若有以下定義與語句:floatr=3.14,*p=&r;*p=2*r;則以下正確的敘述是()。兩處的*p的含義相同,都說明給指針變量p賦值在“floatr=3.14,*p=&r;”中,把r的地址賦值給了p所指的存儲單元語句*p=2*r;把變量r乘以2的值賦值給指針變量p語句*p=2*r;把變量r乘以2的值放回r中ABCD提交單選題5分4.若定義了intm,n=0,*p1=&m;,則下列與m=n;等價的正確語句是()。m=*p1;*p1=&*n;*&p1=&*n;*p1=*&n;ABCD提交單選題5分11.設(shè)有定義:intx[]={1,2,3,4,5,6,7,8,9,0},*p=x,k;且0≤k<10,則對數(shù)組元素x[k]的錯誤引用是()。p+k*(x+k)x[p-x+k]*(&x[k])ABCD提交單選題5分12.設(shè)intb[]={1,2,3,4},y,*p=b;,則執(zhí)行語句y=*p++;之后,變量y的值為()。1234ABCD提交單選題5分【例7.5】已知學(xué)生的考試分?jǐn)?shù)存儲在一維數(shù)組中,編寫函數(shù)統(tǒng)計優(yōu)秀、及格與不及格的學(xué)生人數(shù)。【分析】由于函數(shù)中用return語句只能返回一個值。因此,可以設(shè)置三個指針參數(shù),將統(tǒng)計的結(jié)果分別通過三個參數(shù)傳回給主調(diào)函數(shù)。相應(yīng)地,在主調(diào)函數(shù)中應(yīng)該設(shè)置三個變量,分別將它的們的地址作為實參傳遞給該函數(shù)。#include<stdio.h>#defineN100voidcount(floata[],intn,int*good,int*pass,int*fail);intinput(floata[]);
intmain(){floatscore[N];intn,good,pass,fail;;n=input(score);//輸入分?jǐn)?shù),以負(fù)數(shù)結(jié)束,返回輸入的有效分?jǐn)?shù)個數(shù)if(n>0){count(score,n,&good,&pass,&fail);printf("優(yōu)秀人數(shù):%d\n",good);printf("及格人數(shù):%d\n",pass);printf("不及格人數(shù):%d\n",fail);}return0;}/*@函數(shù)名稱:count入口參數(shù):floata[],intn,int*good,int*pass,int*fail@函數(shù)功能:統(tǒng)計優(yōu)秀、及格與不及格的人數(shù)@出口參數(shù):*good存放優(yōu)秀人數(shù)*pass存放及格人數(shù),*fail存入不及格人數(shù)
*/voidcount(floata[],intn,int*good,int*pass,int*fail){inti;*good=*pass=*fail=0;for(i=0;i<n;i++)if(a[i]>=90)*good+=1;elseif(a[i]>=60)*pass+=1;else(*fail)++;}/*@函數(shù)名稱:input入口參數(shù):floata[]@函數(shù)功能:數(shù)據(jù)輸入
@出口參數(shù):數(shù)據(jù)存入數(shù)組a,函數(shù)返回輸入數(shù)據(jù)的個數(shù)*/intinput(floata[]){inti=-1;printf("請輸入學(xué)生分?jǐn)?shù),以回車分隔(輸入負(fù)數(shù)結(jié)束):\n");do{i++;scanf("%f",a+i);}while(a[i]>=0);returni;}當(dāng)實參對象占用較大空間時,傳地址調(diào)用比傳值調(diào)用具有更高的效率,可以節(jié)約實參向形參數(shù)據(jù)拷貝的時間和存儲實參數(shù)據(jù)的空間。如何限制函數(shù)對形參指針指向的對象進(jìn)行修改?#include<stdio.h>voidfun(constint*x){ printf("%d",*x); //輸出*x *x=20; //編譯錯}intmain(){ inta=10; fun(&a);}指針與一維數(shù)組7.57.5.1指針的算術(shù)運算與關(guān)系運算指針作為一種特殊的數(shù)據(jù)類型,可以進(jìn)行算術(shù)與關(guān)系運算,其中算術(shù)運算僅限加法與減法。指針的算術(shù)運算與關(guān)系運算的含義有別與普通數(shù)據(jù)類型的相關(guān)操作,它是以其基類型為單位展開的。1、指針加上某正整數(shù)當(dāng)指針(常量或變量)p與某正整數(shù)x相加時,會得到一個新的指針值(記為q),q指向p所指單元的后續(xù)x單元。例如,若有shortinta[8],*p,*q,*r;下面的示例說明指針的加法運算。p=&a[3];p指向a[3],如圖7-9所示。執(zhí)行q=p+2;將使q指向a[5]。1、指針加上某正整數(shù)執(zhí)行q++后,q指向a[6]。1、指針加上某正整數(shù)2、指針減去某正整數(shù)當(dāng)x為正整數(shù)時,指針p-x所得的值為內(nèi)存中相對于p的前x單元地址。執(zhí)行r=p-2后,r指向a[1]。當(dāng)x為正整數(shù)時,指針p-x所得的值為內(nèi)存中相對于p的前x單元地址。在此基礎(chǔ)上執(zhí)行r--,將使r指向a[0]。2、指針減去某正整數(shù)當(dāng)x為正整數(shù)時,指針p-x所得的值為內(nèi)存中相對于p的前x單元地址。在此基礎(chǔ)上執(zhí)行r--,將使r指向a[0]。2、指針減去某正整數(shù)3、指針相減p-s的值是多少?'a'0'b'1'c'2'd'345678910'\0''e''f''g''h'sp指向同一個數(shù)組的兩個指針相減,將得到兩個指針間相差的單元個數(shù)。例如,在上圖中,p-r的值為3;p-q的值為-3。3、指針相減4、指針的關(guān)系運算
指針的關(guān)系運算用于比較兩個指針指向單元地址的大小關(guān)系,通常進(jìn)行關(guān)系運算的指針應(yīng)指向同一個數(shù)組才是有意義的。如在上圖中,關(guān)系運算r==p-3的結(jié)果為邏輯真,r<q的結(jié)果也為邏輯真。13.設(shè)有定義:intx[]={1,2,3,4,5},*p=x;,則值為3的表達(dá)式是()。p+=2,*p++p+=2,*++pp+=2,p++p+=2,++*pABCD提交單選題5分7.5.2應(yīng)用指針訪問一維數(shù)組
指針常量a+0a+1a+2pp+1p+2a+i等價于&a[i]*(a+i)等價于a[i]此時:p+i等價于&a[i]*(p+i)等價于a[i]【例7.6】應(yīng)用指針訪問一維數(shù)組示例1。#include<stdio.h>#defineN10intmain(){inta[N],i,*p;p=a; //或?qū)懗蓀=&a[0]printf("請輸入%d個整數(shù):\n",N);for(i=0;i<N;i++)scanf("%d",p+i); 【例7.6】應(yīng)用指針訪問一維數(shù)組示例1。printf("數(shù)組內(nèi)容(從前向后)\n");for(i=0;i<N;i++)printf(“%4d”,p[i]); //或用*(p+i)return0;}【例7.7】應(yīng)用指針訪問一維數(shù)組示例2。#include<stdio.h>#defineN10intmain(){inta[N],*p;printf("請輸入%d個整數(shù):\n",N);for(p=a;p<a+N;p++)//a+N表示a[N-1]的下一單元地址scanf("%d",p);printf("數(shù)組內(nèi)容(從前向后)\n");【例7.7】應(yīng)用指針訪問一維數(shù)組示例2。for(p=a;p<a+N;p++) printf("%5d",*p);
printf("\n數(shù)組內(nèi)容(從后向前)\n");
p=a+N-1; //p指向a[N-1]while(p>=a)printf("%5d",*p--);return0;}請輸入10個整數(shù):12345678910↙數(shù)組內(nèi)容(從前向后)12345678910數(shù)組內(nèi)容(從后向前)10987654321在使用時,要注意區(qū)分*p++與以下幾種表達(dá)式的差別:(*p)++ 自增前表達(dá)式的值是*p,以后再自增*p*++p或*(++p) 先自增p,自增后表達(dá)式的值是*p++*p或++(*p) 先自增*p,自增后表達(dá)值的值是*p10213243456789105pprintf(“%d”,*p);1練習(xí)七15(2)講解10213243456789105pprintf(“%d”,*(++p));練習(xí)七15(2)講解10213243456789105pprintf(“%d”,*(++p));2練習(xí)七15(2)講解10213243456789105pprintf(“%d”,*++p);練習(xí)七15(2)講解10213243456789105pprintf(“%d”,*++p);3練習(xí)七15(2)講解10213243456789105pprintf(“%d”,*(p--));3練習(xí)七15(2)講解10213243456789105pprintf(“%d”,*(p--));3練習(xí)七15(2)講解10213243456789105pprintf(“%d”,*p++);2練習(xí)七15(2)講解10213243456789105pprintf(“%d”,*p++);2練習(xí)七15(2)講解10213243456789105pprintf(“%d”,*p);3練習(xí)七15(2)講解10213243456789105pprintf(“%d”,++(*p));練習(xí)七15(2)講解10214243456789105pprintf(“%d”,++(*p));4練習(xí)七15(2)講解10214243456789105pprintf(“%d”,*p);4練習(xí)七15(2)講解10214243456789105pprintf(“%d”,(*p)++);4練習(xí)七15(2)講解10215243456789105pprintf(“%d”,(*p)++);4練習(xí)七15(2)講解實際上,函數(shù)形參中的一維數(shù)組的本質(zhì)上是指針變量。voidfun(inta[],intn)等價于voidfun(int*a,intn)7.5.3深入理解一維數(shù)組作函數(shù)參數(shù)的本質(zhì)當(dāng)函數(shù)調(diào)用fun(b,10)發(fā)生時,形參指針變量a將被初始化為實參數(shù)組b的首地址,由于指針變量a指向了數(shù)組b的首地址,在函數(shù)中對a[i]的訪問即是對數(shù)組b[i]的訪問?!纠?.8】采用指針方式編程,將一維數(shù)組進(jìn)行首尾倒置并輸出。#include<stdio.h>#defineN10voidinput(int*p,intn);voidprint(int*p,intn);voidreverse(int*p,intn);/*函數(shù)名稱:reverse入口參數(shù):int*p,intn
函數(shù)功能:實現(xiàn)數(shù)組的首尾倒置
*/voidreverse(int*p,intn){inttemp,*q;q=p+n-1; //q指向數(shù)組的最后一個單元while(p<q){temp=*p;*p=*q;*q=temp;p++;q--;}}/*
函數(shù)名稱:input入口參數(shù):int*p,intn
函數(shù)功能:輸入數(shù)組的前n個元素*/voidinput(int*p,intn){inti;printf("請輸入%d個整數(shù):\n",n);for(i=0;i<n;i++)scanf("%d",p++);//本條語句也可寫成scanf("%d",p+i);}/*函數(shù)名稱:print入口參數(shù):int*p,intn
函數(shù)功能:輸出數(shù)組的前n個元素*/voidprint(int*p,intn){inti;for(i=0;i<n;i++)printf("%4d",*p++);
//本條語句也可寫成printf("%4d",*(p+i));printf("\n");}請輸入10個整數(shù):12345678910↙1234567891010987654321intmain(){inta[N];input(a,N);//輸入數(shù)組aprint(a,N);//輸出數(shù)組areverse(a,N);//倒置數(shù)組aprint(a,N);//輸出數(shù)組areturn0;}14.下面程序運行后的輸出結(jié)果是()。1,44,43,14,1ABCD提交#include<stdio.h>voidf(int*p);intmain(){ inta[5]={1,2,3,4,5},*r=a; f(r); printf("%d\n",*r);}voidf(int*p){ p=p+3; printf("%d,",*p);}單選題5分字符指針7.67.6.1使用字符指針指示字符串常量字符指針可以保存字符串常量的首地址。例如:ptr="MynameisTony";當(dāng)字符指針變量指向某字符串后,可以把該指針變量作為函數(shù)實參,傳遞給字符串處理函數(shù)進(jìn)行調(diào)用。例如,可用strlen(ptr)來獲得ptr所指向的字符串的長度。7.6.1使用字符指針指示字符串常量對圖7-15所示的指針變量ptr執(zhí)行:
ptr="Hello";將使ptr指向新的字符串,如圖7-16所示?!纠?.9】字符指針程序示例。#include<stdio.h>#include<string.h>intmain(){ char*str1="MynameisTony"; char*str2="Hello"; char*temp;【例7.9】字符指針程序示例。 printf("strlen(str1)=%d\n",strlen(str1)); printf("str1:%s\n",str1); printf("str2:%s\n",str2); temp=str1;//交換str1與str2指針的指向
str1=str2; str2=temp;【例7.9】字符指針程序示例。 printf("str1:%s\n",str1); printf("str2:%s\n",str2); return0;}strlen(str1)=15str1:MynameisTonystr2:Hellostr1:Hellostr2:MynameisTony【例7.10】指針訪問字符串示例。#include<stdio.h>#include<string.h>intmain(){ chars[20]="Doyouunderstand?"; char*p; p=s;7.6.2利用字符指針訪問字符串變量7.6.2利用字符指針訪問字符串變量【例7.10】指針訪問字符串示例。 while(*p!='\0') //輸出字符串s putchar(*p++); putchar('\n'); printf("strlen(s)=%d\n",p-s); //輸出字符串長度 return0;}Doyouunderstand?strlen(s)=18【例7.11】編寫一個函數(shù)char*myStrcat(char*t,char*s);實現(xiàn)字符串連接函數(shù)strcat的等價功能,并編寫main函數(shù)進(jìn)行測試。#include<stdio.h>#include<string.h>#defineN80/*@函數(shù)名稱:myStract入口參數(shù):char*t,char*s@函數(shù)功能:字符串連接@出口參數(shù):返回目標(biāo)串首地址*/char*myStrcat(char*t,char*s){char*p=t; //保存目標(biāo)串首地址while(*p!='\0')//找目標(biāo)串串尾p++;while(*s!='\0')//將字符串s拷貝至字符串t后{
*p++=*s++;}*p='\0';
//置字符串結(jié)束標(biāo)志returnt;}intmain(){charstr1[N]="Computer";charstr2[N]="Science";puts(myStrcat(str1,str2));puts(str1);puts(str2);return0;}ComputerScienceComputerScienceSciencechar*myStrcat(char*t,char*s){char*p=t;while(*p) //找目標(biāo)串串尾p++;while(*p++=*s++); //將字符串s拷貝至字符串t后returnt;}myStrcat函數(shù)還可以簡化為下面的形式:while(*p++=*s++);語句是如何實現(xiàn)字符串拷貝的?16.設(shè)charch,str[4],*strp;,則正確的賦值語句是()。ch="MBA";str="MBA";strp="MBA";*strp="MBA";ABCD提交單選題5分17.設(shè)chars[10],*p=s;,下列語句中錯誤的是()。p=s+5;s=p+s;s[2]=p[4];*p=s[0];ABCD提交單選題5分18.若定義了charch[]={"abc\0def"},*p=ch;,則執(zhí)行printf("%c",*p+4);語句的輸出結(jié)果是()。defde0ABCD提交單選題5分19.設(shè)chars[6],*ps=s;,則正確的賦值語句是()。s="12345";*s="12345";ps="12345";*ps="12345";ABCD提交單選題5分20.以下程序段的輸出結(jié)果是()。chara[]=“ABCDE”,char*p;for(p=a;p<a+5;p++)
printf("%s\n",p);ABCDEABCDEEDCBAABCDEBCDECDEDEEABCD提交單選題5分21.以下不能將s所指字符串正確復(fù)制到t所指存儲空間的是()。while(*t=*s){t++;s++;}for(i=0;t[i]=s[i];i++);do{*t++=*s++;}while(*s);for(i=0,j=0;t[i++]=s[j++];);ABCD提交單選題5分指針與二維數(shù)組7.77.7.1列指針對于一個M行N列的二維數(shù)組a可以看成是由M個列為N的一維數(shù)組構(gòu)成的這M個一維數(shù)組分別是a[0]~a[M-1]它們按行優(yōu)先的形式存儲在內(nèi)存中。在二維數(shù)組中a[i]代表第i行的起始地址,這個地稱為列地址,即列指針。對于一個3行4列的二維數(shù)組a,共包含有3個一維數(shù)組:a[0]、a[1]和a[2],如圖7-18所示。7.7.1列指針因a[i]代表第i行首地址,所以a[i]+j則代表a[i][j]的地址,即a[i]+j==&a[i][j]由于a[i]可表示為*(a+i),因此以下幾項均為與a[i][j]地址等價的表達(dá)形式:(1)&a[i][j](2)a[i]+j(3)*(a+i)+j相應(yīng)對,與a[i][j]等價的表達(dá)形式有:(1)*(a[i]+j)(2)*(*(a+i)+j)例如,a[2][2]可表示為:
*(a[2]+2)
或
*(*(a+2)+2)【例7.12】利用指針輸出二維數(shù)組內(nèi)容。#include<stdio.h>intmain(){inta[3][4]={0,1,2,3,4,5,6,7,8,9,10,11};int*p,i,j;p=a[0]; //或p=&a[0][0],或p=*(a+0),或p=*a
【例7.12】利用指針輸出二維數(shù)組內(nèi)容。for(i=0;i<3;i++){for(j=0;j<4;j++)printf("%4d",*p++);printf("\n");}return0;}012345678910117.7.2行指針二維數(shù)組的名稱也是一個指針常量,它同樣記錄了二維數(shù)組在內(nèi)存的起始地址。該指針邏輯上具有特殊的含義,對該指針執(zhí)行算術(shù)運算是以二維數(shù)組每行具有的列數(shù)為基本單位的,因此我們稱它為行指針。由行指針向列指針轉(zhuǎn)換的方法為在行指針前面加上間接尋址運算符*。例如:*(a+1)==a[1]*(a+2)==a[2]C語言允許我們定義行指針變量來指向二維數(shù)組的行地址。數(shù)據(jù)類型(*指針變量名)[列數(shù)];7.7.2行指針int(*p)[4];例如:定義了一個列數(shù)為4的行指針變量p,p可用于指向列數(shù)為4的二維數(shù)組的行地址。對p執(zhí)行算術(shù)運算是以4個int型單元為基本單位的。例如,p=p+2;將使p向后移動8個單元。注意與int*p[4]的
區(qū)別7.7.2行指針此時,*(*(p+i)+j)等價于a[i][j]7.7.2行指針
【例7.13】利用行指針訪問二維數(shù)組示例#include<stdio.h>intmain(){ inta[3][4]={0,1,2,3,4,5,6,7,8,9,10,11}; int(*p)[4],i,j;
p=a; //將行指針p賦值為數(shù)組首地址
【例7.13】利用行指針訪問二維數(shù)組示例 for(i=0;i<3;i++) { for(j=0;j<4;j++) printf("%4d",*(*(p+i)+j)); printf("\n"); } return0;}7.7.3深入理解二維數(shù)組作函數(shù)參數(shù)的本質(zhì)*voidfun(inta[][N])等價于voidfun(int(*a)[N])行指針,可保存列為N的二維數(shù)組的行地址
【例7.14】行指針作函數(shù)參數(shù)示例。voidprint(int(*p)[4],intm) //p為列為4的行指針{inti,j;for(i=0;i<m;i++){for(j=0;j<4;j++) printf("%4d",*(*(p+i)+j));printf("\n");}}或?qū)懗蓀rintf("%4d",p[i][j]);
【例7.14】行指針作函數(shù)參數(shù)示例。intmain(){inta[3][4]={0,1,2,3,4,5,6,7,8,9,10,11};intb[2][4]={1,3,5,7,2,4,6,8};printf("a:\n");print(a,3); //以二維數(shù)組名a為實參printf("b:\n");print(b,2); //以二維數(shù)組名b為實參return0;}25.設(shè)inta[3][4];,則與元素a[0][0]不等價的表達(dá)形式是()。*a**a*a[0]*(*(a+0)+0)ABCD提交單選題5分26.下列程序的運行結(jié)果是()。9111719ABCD提交intmain(){
inta[][4]={1,3,5,7,9,11,13,15,17,19,21,23};
int(*p)[4],i=2,j=1;
p=a;
printf("%d\n",*(*(p+i)+j));}單選題5分27.設(shè)inta[3][2]={2,4,6,8,10,12};,則*(a[2]+1)的值是
[填空1]
。作答填空題5分29.有定義語句:int*p[4];,以下選項中與此語句等價的是()。intp[4];int**p;int*(p[4]);int(*p)[4];ABCD提交單選題5分30.以下程序運行的結(jié)果是什么()。3,3,32,2,31,2,31,1,3ABCD提交#include<stdio.h>#include<stdlib.h>intmain(){int*a,*b,*c;
a=b=c=(int*)malloc(sizeof(int));
*a=1; *b=2; *c=3;
a=b;
printf("%d,%d,%d\n",*a,*b,*c);
free(a);
return0;}單選題5分7.7.4巧用列指針設(shè)計通用二維數(shù)組處理函數(shù)*a[i][j]相對a[0][0]的偏移量為i*N+j&a[i][j]==&a[0][0]+i*N+j例如,若a為3行4列的數(shù)組,則a[2][2]相對于a[0]的偏移量為2*4+2,因此其地址是a[0]+10,相應(yīng)地a[2][2]可用*(a[0]+10)等價地表示。7.7.4巧用列指針設(shè)計通用二維數(shù)組處理函數(shù)*利用上述特性,我們可以通過將二維數(shù)組的首地址(列地址)傳遞給形參為列指針的函數(shù),在函數(shù)中利用二維地址到一維地址的映射關(guān)系來訪問二維數(shù)組元素。7.7.4巧用列指針設(shè)計通用二維數(shù)組處理函數(shù)*【例7.15】分別編寫能夠輸入和輸出任意行,任意列的二維數(shù)組函數(shù)。#include<stdio.h>/*@函數(shù)名稱:input入口參數(shù):int*a,intm,intn@函數(shù)功能:輸入m行n列的整型二維數(shù)組*/voidinput(int*a,intm,intn) {inti,j;printf("請輸入%d行,%d列的二維數(shù)組:\n",m,n);for(i=0;i<m;i++)for(j=0;j<n;j++)scanf("%d",a+i*n+j);//或scanf("%d",&a[i*n+j]);}【例7.15】分別編寫能夠輸入和輸出任意行,任意列的二維數(shù)組函數(shù)。/*@函數(shù)名稱:print入口參數(shù):int*a,intm,intn@函數(shù)功能:輸出m行n列的整型二維數(shù)組*/voidprint(int*a,intm,intn){inti,j;for(i=0;i<m;i++){for(j=0;j<n;j++)printf("%4d",*(a+i*n+j)); //或printf("%4d",a[i*n+j]);printf("\n");}}intmain(){inta[2][4];intb[3][3];input(*a,2,4);//傳入a[0][0]的地址,input(&b[0][0],3,3);printf("數(shù)組a:\n");print(a[0],2,4);printf("數(shù)組b:\n");print(b[0],3,3);return0;}請輸入2行,4列的二維數(shù)組:12345678請輸入3行,3列的二維數(shù)組:123456789數(shù)組a:12345678數(shù)組b:123456789指針的高級應(yīng)用7.87.8.1指針數(shù)組其應(yīng)用1、指針數(shù)組的定義數(shù)據(jù)類型*指針數(shù)組名[數(shù)組大小];char*str[6]={"ThinkinJava","Cprogramminglanguage","DataStructure","AWriter\'sReference","Englishinuse"};7.8.1指針數(shù)組其應(yīng)用【例7.14】利用指針數(shù)組輸出程序菜單示例。#include<stdio.h>#include<string.h>intmain(){char*str[]={"[1]加法","[2]減法","[3]乘法","[4]除法","[5]設(shè)置題量大小","[6]設(shè)置答題機會","[0]退出"};intlen,i;
len=sizeof(str)/sizeof(char*); //求數(shù)組大小for(i=0;i<len;i++)puts(str[i]);return0;}2、指針數(shù)組在索引表中的應(yīng)用*物理排序【例7.15】假設(shè)磁盤文件信息存儲在圖7-22所示文件分配表file中(為簡化,我們只存儲了文件(夾)名稱),請編程模擬實現(xiàn)對文件按名稱排序?!咀詫W(xué)】索引表排序#include<stdio.h>#include<string.h>#defineM5#defineN30voidselectSort(char*index[],intn);intmain(){charfile[M][30]; //模擬文件分配表char*index[M]; //索引表inti;printf("請輸入%d個文件名:\n",M);for(i=0;i<M;i++) //輸入文件名gets(file[i]);for(i=0;i<M;i++) //建立初始索引
index[i]=file[i];
selectSort(index,M); //對索引表進(jìn)行排序puts("按名稱排序:");for(i=0;i<M;i++) //按索引輸出文件名
puts(index[i]);return0;}/*@函數(shù)名稱:selectSort入口參數(shù):char*index,intn@函數(shù)功能:采用簡單選擇排序法對索引表排序
*/voidselectSort(char*index[],intn){char*temp;inti,j,minIndex;for(i=0;i<M-1;i++){minIndex=i;for(j=i+1;j<M;j++)if(strcmp(index[j],index[minIndex])<0) minIndex=j;if(minIndex!=i) //交換指針{temp=index[i];index[i]=index[minIndex];index[minIndex]=temp;}}}3、main函數(shù)的命令行參數(shù)Linux等操作系統(tǒng)提供了命令行的操作界面,Windows通過cmd.exe程序向用戶提供命令行操作界面。例如:copyc:\Windows\win.inid:\ping其格式如下:intmain(intargc,char*argv[])
整型變量argc用來記錄命令行命令和參數(shù)的總個數(shù),其值為參數(shù)個數(shù)加1,由C程序運行時自動計算出來;字符型指針數(shù)組argv用來指向命令行中的各個參數(shù),即將每一個以空格為分隔符的參數(shù)視為一個字符串,存放其首地址,argv的容量由argc確定。3、main函數(shù)的命令行參數(shù)【例7.18】命令行參數(shù)示例。#include<stdio.h>intmain(intargc,char*argv[]){inti;printf("argc=%d\n",argc);for(i=0;i<argc;i++)printf("argv[%d]:%s\n",i,argv[i]);return0;}>7_18C++JavaPythonargc=4argv[0]:7_18argv[1]:C++argv[2]:Javaargv[3]:Python7.8.2動態(tài)內(nèi)存分配靜態(tài)分配:static變量與全局變量,程序運行時自動分配,程序結(jié)束時釋放。自動分配:auto型變量,進(jìn)入作用域時自動分配,退出作用域時自動釋放。動態(tài)分配:根據(jù)用戶需求動態(tài)申請與釋放內(nèi)存。1、內(nèi)存分配函數(shù)C語言在<stdlib.h>中定義了三種內(nèi)存分配函數(shù),來實現(xiàn)動態(tài)內(nèi)存分配。malloc函數(shù):用于分配內(nèi)存塊,但是不對內(nèi)存塊進(jìn)行初始化。calloc函數(shù):用于分配內(nèi)存塊,并且對內(nèi)存塊進(jìn)行清零。realloc函數(shù):用于調(diào)整先前分配的內(nèi)存塊大小。(1)malloc函數(shù)void*malloc(size_tsize);例如:int*a,n=6;a=(int*)malloc(n*sizeof(int));
我們可以將a當(dāng)作整型數(shù)組使用,例如:inti;for(i=0;i<n;i++) scanf("%d",&a[i]);
若n值由鍵盤輸入,我們便可以根據(jù)需要動態(tài)構(gòu)造所需的數(shù)組大小。(1)malloc函數(shù)
再如: char*p; p=(char*)malloc(20*sizeof(char)); strcpy(p,"ComputerNetworks");(2)calloc函數(shù)calloc函數(shù)原型如下:
void*calloc(size_tn,size_tsize);
該函數(shù)分配n個連續(xù)的大小為size的內(nèi)存空間。例如:int*a,n=6;a=(int*)calloc(n,sizeof(int));該函數(shù)在分配完后會將所有的單元初始化為0。(3)realloc函數(shù)realloc函數(shù)可以調(diào)整數(shù)組的大小使它更適合需要。
其函數(shù)原型如下:void*realloc(void*ptr,size_tsize);ptr必須指向先前通過malloc、calloc或realloc的調(diào)用獲得的內(nèi)存塊,size表示內(nèi)存塊的新尺寸?!纠?.16】動態(tài)分配數(shù)組示例。#include<stdio.h>#include<stdlib.h>#include<string.h>intmain(){ char*p; p=(char*)malloc(20*sizeof(char)); if(p!=NULL)
【例7.16】動態(tài)分配數(shù)組示例。 { strcpy(p,"ComputerNetworks"); puts(p); } p=(char*)realloc(p,2*strlen(p)); //將數(shù)組空間擴(kuò)大2倍【例7.16】動態(tài)分配數(shù)組示例。 if(p) { puts(p); strcat(p,"andDatastructure"); puts(p); } free(p); //釋放動態(tài)申請的空間 return0;}2、內(nèi)存釋放函數(shù)
其用法為:
free(指針); free(p);
其用法為:
free(指針); free(p);2、內(nèi)存釋放函數(shù)a=b;泄漏的內(nèi)存7.8.3二級指針*1、二級指針的概念
二級指針變量定義格式如下:指針變量也是內(nèi)存變量,因此也有內(nèi)存地址。因此,可以定義指針變量來保存指針變量的地址。我們稱這種變量為指向指針變量的指針變量,簡稱指向指針的指針,常稱為二級指針。數(shù)據(jù)類型
**指針變量;例如: inta=10,*p,**pre; p=&a; pre=&p;2、二級指針的應(yīng)用*(1)當(dāng)函數(shù)需要修改指針變量實參時,可以用指向指針的指針變量作為形式參數(shù),這樣便可接受主調(diào)函數(shù)中指針變量的地址作實參?!纠?.17】main函數(shù)中定義了兩個int*型指針變量p和q,初始時分別指向整型變量a和b,如圖7-29(a)所示。請編寫函數(shù)swap,交換main函數(shù)中p和q的指向,如圖7-29(b)所示。(a)交換前
(b)交換后#include<stdio.h>voidswap(int*p,int*q){int*temp;temp=p;p=q;q=temp;}intmain(){inta=10,b=20;int*p,*q;p=&a;q=&b;printf("*p=%d,*q=%d\n",*p,*q);swap(p,q);
printf("*p=%d,*q=%d\n",*p,*q);}【分析】要在swap函數(shù)中修改main函數(shù)中的p與q,需要將p與q的地址傳遞給swap函數(shù),因此,需要將swap函數(shù)的形參設(shè)計為int**型指針變量。#include<stdio.h>voidswap(int**p1,int**q1){int*temp;temp=*p1;*p1=*q1;*q1=temp;}intmain(){inta=10,b=20;int*p,*q;p=&a;q=&b;printf("*p=%d,*q=%d\n",*p,*q);swap(&p,&q);//此處用的是指針變量的地址作實參printf("*p=%d,*q=%d\n",*p,*q);}*p=10,*q=20*p=20,*q=10(2)當(dāng)需要采用動態(tài)分配內(nèi)存的方法生成指針變量或指針數(shù)組時,需要定義指向指針的指針變量來存儲指針變量的地址。【例7.18】請設(shè)計如圖7-30所示的一個不規(guī)則的二維數(shù)組,計算并存儲楊輝三角。p[0][0]p[0]p[1]……p[m-2]p[m-1]p[1][0]p[1][1]p[m-1][0]p[m-1][1] … …p[m-1][n-1]p編寫程序采用動態(tài)二維數(shù)組實現(xiàn)楊輝三角111121#include<stdio.h>#include<stdlib.h>/*@函數(shù)名稱:yanghui入口參數(shù):intm@函數(shù)功能:動態(tài)生成并計算存儲m行楊輝三角的不規(guī)則二維數(shù)組*/int**yanghui(intm){int**p;inti,j;//以下代碼生成m行的不規(guī)則二維數(shù)組(下三角二維數(shù)組)
p=(int**)malloc(m*sizeof(int*)); //生成指針數(shù)組for(i=0;i<m;i++)
p[i]=(int*)malloc((i+1)*sizeof(int));
//第i行申請i+1個單元
//求解楊輝三角for(i=0;i<m;i++){p[i][0]=p[i][i]=1;for(j=1;j<i;j++)p[i][j]=p[i-1][j]+p[i-1][j-1];}returnp; //返回指針數(shù)組首地址}intmain(){intm,i,j;int**p;printf("請輸入楊輝三角的行數(shù):\n");scanf("%d",&m);p=yanghui(m);//輸出楊輝三角for(i=0;i<m;i++){
for(j=0;j<=i;j++)printf("%5d",p[i][j]);printf("\n");}
//釋放動態(tài)生成的二維數(shù)組for(i=0;i<m;i++)free(p[i]); //釋放數(shù)組的每一行free(p); //釋放指針數(shù)組return0;}7.8.4指向函數(shù)的指針及其應(yīng)用*指向函數(shù)的指針定義格式為:
函數(shù)返回類型(*指針名)(參數(shù)列表);例如:
int(*f)(inta,intb);
定義了一個函數(shù)指針,該指針可以保存返回類型為int,且參數(shù)為兩個int型數(shù)據(jù)的函數(shù)地址。若有兩個函數(shù)定義:intmaxValue(inta,intb){ returna>b?a:b;}intminValue(inta,intb){ returna<b?a:b;}f=maxValue;(*f)(10,20);等價于maxValue(10,20);f=minValue;(*f)(10,20);等價于minValue(10,20);【例7.22】利用函數(shù)指針實現(xiàn)既可遞增又可遞減排序的冒泡排序函數(shù)。#include"Array.h" //引用第6章設(shè)計的Array.h文件 //請將其拷貝至本文件夾#defineN10intascend(inta,intb){returna>b?1:0;}intdescend(inta,intb){returna<b?1:0;}/*@函數(shù)名稱:bubbleSort@入口參數(shù):inta[],intn,int(*f)(int,int)@函數(shù)功能:采用冒泡排序法對數(shù)組a進(jìn)行遞增排序或遞減排序*/【例7.22】利用函數(shù)指針實現(xiàn)既可遞增又可遞減排序的冒泡排序函數(shù)。voidbubbleSort(inta[],intn,int(*f)(int,int)){inti,flag=1,temp;while(n>1&&flag==1){flag=0;for(i=0;i<n-1;i++)if((*f)(a[i],a[i+1])==1){temp=a[i];a[i]=a[i+1];a[i+1]=temp;flag=1;}}}intmain(){inta[N];init(a,N);
//用隨機函數(shù)生成N個測試數(shù)據(jù)print(a,N);bubbleSort(a,N,ascend);//升序排序print(a,N);bubbleSort(a,N,descend);//降序排序print(a,N);return0;}通過本章的學(xué)習(xí)應(yīng)達(dá)到以下要求:(1)了解指針的本質(zhì),掌握指針變量的定義與初始化方法,掌握利用指針進(jìn)行間接訪問變量的方式。(2)理解值傳遞與地址傳遞的區(qū)別,掌握指針作函數(shù)參數(shù)時的參數(shù)傳遞方式。(3)掌握應(yīng)用指針訪問一維數(shù)組的方法,理解指針的算術(shù)運算與關(guān)系運算的含義。(4)掌握使用字符指針表示及訪問字符串的方法。本章小結(jié)(5)理解行指針、列指針的基本概念,理解二維數(shù)組作函數(shù)參數(shù)的本質(zhì)。(6)掌握指針數(shù)組的定義及其使用方法。(7)掌握動態(tài)內(nèi)存分配函數(shù)及其使用方法。(8)領(lǐng)會二級指針的概念及其應(yīng)用場合。本章小結(jié)實驗七1.采用指針法編寫函數(shù)myStrcmp(char*t,char*s),實現(xiàn)與strcmp等價的功能。2.編寫函數(shù)實現(xiàn)在任意行、任意列的二維數(shù)組中尋找鞍點,行、列數(shù)均由主調(diào)函數(shù)傳入,編寫測試程序進(jìn)行測試。3.編寫一個函數(shù)實現(xiàn)m行、n列的矩陣乘以n行、k列的矩陣,m、n與k均要求由主調(diào)函數(shù)傳入,編寫測試程序進(jìn)行測試。實驗七4.采用指針編程,實現(xiàn)能夠輸入和輸出任意行、任意列的二維數(shù)組函數(shù)。5.m名
溫馨提示
- 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)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 二零二五年度文化藝術(shù)界員工勞動合同范本2篇
- 二零二五年度大蒜種植基地與電商平臺物流配送合同3篇
- 二零二五年度房產(chǎn)中介保密協(xié)議示范文本9篇
- 二零二五年度房屋抵押貸款與資產(chǎn)證券化合同范本3篇
- 二零二五年度建筑安裝工程安全應(yīng)急預(yù)案編制合同3篇
- 二零二五年度房地產(chǎn)開發(fā)項目合作智慧城市建設(shè)合作協(xié)議范本3篇
- 縱向推書機構(gòu)課程設(shè)計
- 二零二五年度步行街商鋪租賃與綠色能源使用協(xié)議合同3篇
- 二零二五年度房地產(chǎn)銷售代理服務(wù)合同(含綠色環(huán)保建材)3篇
- 海南衛(wèi)生健康職業(yè)學(xué)院《拓展運動課程設(shè)計》2023-2024學(xué)年第一學(xué)期期末試卷
- 米吳科學(xué)漫畫奇妙萬象篇
- 河南省鄭州市金水區(qū)2022-2023學(xué)年三年級上學(xué)期期末數(shù)學(xué)試卷
- XXX酒店開辦費POB預(yù)算
- Z矩陣、Y矩陣、A矩陣、S矩陣、T矩陣定義、推導(dǎo)及轉(zhuǎn)換公式
- 中美歐規(guī)范樁基承載力計算設(shè)計對比
- 外科洗手操作考核評分表
- 復(fù)旦大學(xué)外國留學(xué)生入學(xué)申請表
- 長安汽車發(fā)動機水溫高故障案例分析處置
- 瞬時單位線法計算洪水
- 氣力輸灰安裝施工方案
- 抗精神疾病藥物與麻醉課件
評論
0/150
提交評論