版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
第6章指針
指針是C語(yǔ)言中的一個(gè)重要概念,是其最具特色的語(yǔ)言部分,也是C語(yǔ)言的精華,同時(shí)也是C語(yǔ)言的難點(diǎn)。指針可以有效地表示復(fù)雜的數(shù)據(jù)結(jié)構(gòu);能動(dòng)態(tài)分配內(nèi)存;方便地使用字符串;有效而方便地使用數(shù)組;在調(diào)用函數(shù)時(shí)能獲得1個(gè)以上的結(jié)果;能直接處理內(nèi)存單元的地址等。6.1.1地址和指針的概念
內(nèi)存是計(jì)算機(jī)的一個(gè)重要組成部分,用于存放那些“正在”使用的數(shù)據(jù)和“正在”執(zhí)行的程序。內(nèi)存單元的基本單位是字節(jié),為了方便對(duì)內(nèi)存的訪問(wèn),每一個(gè)內(nèi)存單元都有一個(gè)編號(hào),就像門(mén)牌號(hào)一樣,這個(gè)編號(hào)就是內(nèi)存的地址。C程序中的每一個(gè)變量,C程序的每一個(gè)函數(shù),在內(nèi)存中都會(huì)對(duì)應(yīng)一定的內(nèi)存單元。
1.內(nèi)存地址——內(nèi)存中存儲(chǔ)單元的編號(hào)6.1.1地址和指針的概念
編譯時(shí)系統(tǒng)分配2000和2001兩個(gè)字節(jié)給變量i,2002和2003兩個(gè)字節(jié)給變量j,2004和2005兩個(gè)字節(jié)給變量k。2.變量的地址——系統(tǒng)分配給變量的內(nèi)存單元的起始地址
如果在程序中定義了一個(gè)變量,在對(duì)程序進(jìn)行編譯時(shí),系統(tǒng)就會(huì)給這個(gè)變量分配一個(gè)或若干個(gè)存儲(chǔ)單元。不同的數(shù)據(jù)類(lèi)型分配不同字節(jié)的存儲(chǔ)空間。
每一字節(jié)都有一個(gè)地址,一般把每個(gè)數(shù)據(jù)的首字節(jié)地址稱(chēng)為該數(shù)據(jù)的地址。假如有如下定義:inti,j,k;6.1.1地址和指針的概念3.變量值的存取——通過(guò)變量在內(nèi)存中的地址進(jìn)行在程序中一般是通過(guò)變量名來(lái)對(duì)內(nèi)存單元進(jìn)行存取操作的。其實(shí)程序經(jīng)過(guò)編譯以后己經(jīng)將變量名轉(zhuǎn)換為變量的地址,對(duì)變量值的存取都是通過(guò)地址進(jìn)行的。6.1.1地址和指針的概念②系統(tǒng)對(duì)語(yǔ)句“scanf("%d",&i);”在執(zhí)行時(shí),如果從鍵盤(pán)輸入3,表示要把3送到變量i中,實(shí)際上是把3送到地址為2000開(kāi)始的整型存儲(chǔ)單元中。(1)直接訪問(wèn)——直接利用變量的地址進(jìn)行存取。①對(duì)于語(yǔ)句“printf("%d",i);”它是這樣執(zhí)行的:根據(jù)變量名與地址的對(duì)應(yīng)關(guān)系(這個(gè)對(duì)應(yīng)關(guān)系是在編譯時(shí)確定的),找到變量i的地址2000,然后從由2000開(kāi)始的兩個(gè)字節(jié)中取出數(shù)據(jù)(即變量的值),把它輸出。這里輸出的值為3。
則從2000和2001字節(jié)取出i的值(3),再?gòu)?002和2003字節(jié)取出j的值(假設(shè)為6),將它們相加后再將其和(9)送到k所占用的2004和2005字節(jié)單元中。這種按變量地址存取變量值的方式稱(chēng)為“直接訪問(wèn)”方式。如果有語(yǔ)句:k=i+j;6.1.1地址和指針的概念
要存取變量i的值,也可以采用間接方式:先找到存放“i的地址”的變量i_pointer,從中取出i的地址(2000),然后到2000和2001字節(jié)取出i的值(3)。
(2)間接訪問(wèn)——通過(guò)另外一個(gè)變量訪問(wèn)該變量的值。C語(yǔ)言規(guī)定,可以在程序中定義整型變量、浮點(diǎn)型變量、字符變量等,也可以定義這樣一種特殊的變量,它是存放地址的。
假設(shè)定義了一個(gè)變量i_pointer,用來(lái)存放整型變量的地址,它被分配為3010和3011兩個(gè)字節(jié)??梢酝ㄟ^(guò)下面的語(yǔ)句將i的起始地址(2000)存放到i_pointer中。i_pointer=&i;這時(shí),i_pointer的值就是2000,即變量i所占用單元的起始地址。6.1.1地址和指針的概念圖6-2(a)表示直接訪問(wèn),已經(jīng)知道變量i的地址,根據(jù)此地址直接對(duì)變量i的存儲(chǔ)單元進(jìn)行存取訪問(wèn)(圖示把數(shù)值3存放到i中)。6-2(a) 6-2(b)間接訪問(wèn)(3)兩種訪問(wèn)方式的比較。圖6-2(b)表示間接訪問(wèn),先找到存放變量i地址的變量i_pointer,從其中得到變量i的地址,再據(jù)此找到變量i的存儲(chǔ)單元,然后對(duì)它進(jìn)行存取訪問(wèn)。6.1.1地址和指針的概念指針變量的值(即指針變量中存放的值)是地址(即指針)。一個(gè)變量的地址稱(chēng)為該變量的“指針”。例如,地址2000是變量i的指針。如果有一個(gè)變量專(zhuān)門(mén)用來(lái)存放另一個(gè)變量的地址(即指針),則它稱(chēng)為“指針變量”,指針變量就是地址變量(存放地址的變量)。6.1.2指向變量的指針變量定義了兩個(gè)整型變量x和y,一個(gè)指針變量p。2.指針變量的定義與應(yīng)用
與一般變量的定義相比,除變量名前多了一個(gè)星號(hào)“*”(指針變量的定義標(biāo)識(shí)符)外,其余一樣:數(shù)據(jù)類(lèi)型*指針變量[,指針變量2……];例如:intx=10,*p,y;6.1.2指向變量的指針變量#include"stdio.h"voidmain(){intnum_int=12,*p_int; floatnum_f=3.14,*p_f; charnum_ch='p',*p_ch; p_int=&num_int; p_f=&num_f; p_ch=&num_ch; printf("num_int=%d,*p_int=%d\n",num_int,*p_int);printf("num_f=%d,*p_f=%d\n",num_f,*p_f);printf("num_ch=%d,*p_ch=%d\n",num_ch,*p_ch);}程序的運(yùn)行結(jié)果為:num_int=12,*p_int=12num_f=3.14,*p_f=3.14num_ch=p,*p_ch=p【例6.1】指針變量的定義。/*定義一個(gè)指向int型數(shù)據(jù)的指針變量p_int*//*定義一個(gè)指向float型數(shù)據(jù)的指針變量p_f*//*定義一個(gè)指向char型數(shù)據(jù)的指針變量p_ch*//*取變量num_int的地址,賦值給p_int*//*取變量num_f的地址,賦值給p_f*//*取變量num_ch的地址,賦值給p_ch*/6.1.2指向變量的指針變量P=&x;y=*p;
指針變量p與整型變量x的關(guān)系
取地址運(yùn)算的格式:&變量例如:intx=10,*p,y;/*取變量x的地址賦給指針變量p*//**p表示取指針變量p所指單元的內(nèi)容,即變量x的值,則y=10*/6.1.2指向變量的指針變量if(p==NULL){……}其含義是:判斷指針p是否為空,若指針p為空,則表達(dá)式成立。
在C語(yǔ)言中,如果intx=10,y,*px;且有px=&x;則變量x與指向變量x的指針px之間有以下等價(jià)關(guān)系:y=x;等價(jià)于y=*px;/*y=指針變量px的內(nèi)容*/x++;等價(jià)于(*px)++;/*對(duì)指針變量px的內(nèi)容加1*/y=x+5等價(jià)于y=(*px)+5;y=x;等價(jià)于y=*(&x);/*y=變量x地址的內(nèi)容*/p=NULL;表示指針p為空,沒(méi)有指向任何對(duì)象。C語(yǔ)言中用NULL表示空指針。6.1.2指向變量的指針變量#include"stdio.h"voidmain(){intnum1,num2;int*num1_p=&num1,*num2_p=&num2,*pointer;printf("inputthefirstnumber:");scanf("%d",num1_p);printf("inputthesecondnumber:");scanf("%d",num2_p);printf("num1=%d,num2=%d\n",num1,num2);fi(*unm1_p>*num2_p){pointer=numi_p;num1_p=num2_p;num2_p=pointer;}printf("min=%d,max=%d\n",*num1_p,*num2_p);}【例6.2】輸入兩個(gè)整數(shù),按升序(從小到大排序)輸出。/*如果num1>num2,則交換指針*/程序運(yùn)行情況如下:inputthefirstnumber:9↙inputthesecondnumber:6↙num1=9,num2=6min=6,max=96.2指針與數(shù)組引用數(shù)組元素可以用下標(biāo)法(如a[3]),也可以用指針的方法,即通過(guò)指向數(shù)組元素的指針找到所需的元素。
一個(gè)變量有一個(gè)地址,一個(gè)數(shù)組包含若干個(gè)元素,每個(gè)數(shù)組元素都在內(nèi)存中占有存儲(chǔ)單元,它們都有相應(yīng)的地址。指針變量既然可以指向變量,也可以指向數(shù)組和數(shù)組元素。數(shù)組的指針是指數(shù)組的起始地址,數(shù)組元素的指針就是數(shù)組元素的地址。6.2.1指向數(shù)組元素的指針指向數(shù)組元素的指針變量的定義,與指向普通變量的指針變量的定義方法一樣。例如:intarray[10];(定義array為包含10個(gè)整型變量的數(shù)組)int*pointer;(定義pointer為指向整型變量的指針變量)對(duì)指針變量的賦值:pointer=&array[0];
把a(bǔ)rray[0]元素的地址賦給指針變量pointer。也就是說(shuō),pointer指向array數(shù)組的第0號(hào)(第1個(gè))元素。6.2.1指向數(shù)組元素的指針C語(yǔ)言規(guī)定數(shù)組名代表數(shù)組的首地址,也就是第一個(gè)元素的地址。
數(shù)組名不代表整個(gè)數(shù)組,上述“pointer=array;”的作用是“把a(bǔ)rray數(shù)組的第一個(gè)元素的地址賦給指針變量pointer”,而不是“把a(bǔ)rray數(shù)組各元素的值賦給pointer”。下面兩個(gè)語(yǔ)句等價(jià):pointer=&array[0];pointer=array;注意:6.2.1指向數(shù)組元素的指針
它的作用是把a(bǔ)rray數(shù)組的第一個(gè)元素的地址賦給指針變量pointer。在定義指針變量時(shí)可以對(duì)它賦初值。int*pointer=&array[0];它等效于:int*pointer;pointer=&array[0];定義時(shí)也可以寫(xiě)成:int*pointer=array;6.2.2通過(guò)指針引用數(shù)組元素
指向數(shù)組的指針變量,也可將其看作數(shù)組名,因而可按下標(biāo)法來(lái)使用。1.通過(guò)指針引用一維數(shù)組中的元素如果有intarray[10],*pointer=array;則:*(pointer+i)和*(array+i)就是數(shù)組元素array[i]。pointer+i和array+i都是數(shù)組元素array[i]的地址。例如,pointer[i]等價(jià)于*(pointer+i)。6.2.2通過(guò)指針引用數(shù)組元素#include"stdio.h"#include"ctype.h"main(){intarray[10],*pointer=array,i;printf("Input10numbers:");for(i=0;i<10;i++)scanf("%d",pointer+i); printf("array[10]:");for(i=0;i<10;i++)printf("%d",*(pointer+i));printf("\n");}程序的運(yùn)行情況如下:Input10numbers:0123456789↙Array[10]:0123456789【例6.3】使用指向數(shù)組的指針變量來(lái)引用數(shù)組元素。/*使用指針變量來(lái)輸入數(shù)組元素的值*//*使用指向數(shù)組的指針變量輸出數(shù)組*/6.2.2通過(guò)指針引用數(shù)組元素(4)關(guān)系運(yùn)算:表示兩個(gè)指針?biāo)傅刂分g、位置的前后關(guān)系:前者為小,后者為大。說(shuō)明:(1)指針變量的值是可以改變的,所以必須知道其當(dāng)前值,否則容易出錯(cuò)。(2)指向數(shù)組的指針變量,可以指向數(shù)組以后的內(nèi)存單元,但是沒(méi)有實(shí)際意義。(3)對(duì)指向數(shù)組的指針變量(px和py)進(jìn)行算術(shù)運(yùn)算和關(guān)系運(yùn)算的含義如下:px±n:將指針當(dāng)前位置向前(+n)或后退(-n)n個(gè)數(shù)據(jù)單位,而不是n個(gè)字節(jié)px++/++px,px--/--px是px±n的特例(n=1)。px-py:兩指針之間的數(shù)據(jù)個(gè)數(shù),而不是指針的地址之差。6.2.2通過(guò)指針引用數(shù)組元素其中:a為數(shù)組的首地址,M和N分別為二維數(shù)組行和列的元素個(gè)數(shù)。2.通過(guò)指針引用二維數(shù)組中的元素
在C語(yǔ)言中,二維數(shù)組是按行優(yōu)先的規(guī)律轉(zhuǎn)換為一維線性數(shù)組存放在內(nèi)存中的,因此,可以通過(guò)指針訪問(wèn)二維數(shù)組中的元素。如果有:inta[M][N];則將二維數(shù)組中的元素a[i][j]轉(zhuǎn)換為一維線性地址的一般公式是:線性地址=a+i×M+j6.2.2通過(guò)指針引用數(shù)組元素則二維數(shù)組a的數(shù)據(jù)元素在內(nèi)存中的存儲(chǔ)順序及地址關(guān)系如圖6-4所示。若有:inta[4][3],*p;P=&a[0][0];圖6-4二維數(shù)組的元素在內(nèi)存中的存儲(chǔ)順序及地址關(guān)系數(shù)組名稱(chēng)含義a[0]a[0][0]一維下標(biāo)的指針二維數(shù)組的下標(biāo)表示元素在內(nèi)存中的存儲(chǔ)順序通過(guò)指針訪問(wèn)元素通過(guò)指針按下標(biāo)訪問(wèn)元素aa[1]a[2]a[3]a[0][1]a[0][2]a[1][0]a[1][1]a[1][2]a[2][0]a[2][1]a[2][2]a[3][0]a[3][1]a[3][2]pP+1P+2P+3P+4P+5P+6P+7P+8P+9P+10P+11p[0]p[1]p[2]P[3]p[4]p[5]p[6]p[7]p[8]p[9]p[10]p[11]6.2.2通過(guò)指針引用數(shù)組元素?cái)?shù)組元素a[i][j]的存儲(chǔ)地址是:&a[0][0]+i*n+j。a和a[0]是數(shù)組元素a[0][0]的地址,也是第1行的起始地址。a+1和a[1]是數(shù)組元素a[1][0]的地址,也是第2行的起始地址。由于a是二維數(shù)組,經(jīng)過(guò)兩次下標(biāo)運(yùn)算[]之后才能訪問(wèn)到數(shù)組元素。所以根據(jù)C語(yǔ)言的地址計(jì)算方法,a要經(jīng)過(guò)兩次*操作后才能訪問(wèn)到數(shù)組元素。6.2.2通過(guò)指針引用數(shù)組元素算法分析:給定的月是i,則將1,2,3,…,i-1月的各月的天數(shù)累加,再加上指定的日。但對(duì)于閏年,二月的天數(shù)為29天,因此還要判斷給定的年是否為閏年,為了實(shí)現(xiàn)這一算法,需要設(shè)置一張每月天數(shù)的列表,給出每月的天數(shù),考慮閏年非閏年的情況,此表可以設(shè)置成一個(gè)兩行13列的二維數(shù)組,其中第1行對(duì)應(yīng)的每列(設(shè)1~12列有效)元素是平年各月的天數(shù),第2行對(duì)應(yīng)的是閏年各月的天數(shù)?!纠?.4】給定某年某月某日,將其轉(zhuǎn)換成這一年的第幾天并輸出。6.2.2通過(guò)指針引用數(shù)組元素#include"stdio.h"#include"ctype.h"main(){Staticintday_tab[2][13]={{0,31,28,31,30,31,30,31,31,30,31,30,31},{0,31,29,31,30,31,30,31,31,30,31,30,31}};inty,m,d;scanf("%d%d%d",&y,&m,&d);printf("%d\n",day_of_year(day_tab,y,m,d)); }day_of_year(day_tab,year,month,day)int*day_tab; intyear,month,day;{inti,j;i=(year%4==0&&year%100!=0)||year%400==0;for(j=1;j<month;j++)day+=*(day_tab+i*13+j);return(day);}/*實(shí)參為二維數(shù)組名*//*形式參數(shù)為指針*//*day_tab+i*13+j;對(duì)二維數(shù)組中元素進(jìn)行地址變換*/6.2.3數(shù)組名作為函數(shù)參數(shù)當(dāng)數(shù)組名作為實(shí)參時(shí),如果形參數(shù)組中各元素的值發(fā)生了變化,實(shí)參數(shù)組元素的值也隨之變化。數(shù)組名作為函數(shù)的形參和實(shí)參。如:main(){intarray[10];f(array,10);}f(arr,n)intarr[],n;{
…}array為實(shí)參數(shù)組名,arr為形參數(shù)組名6.2.3數(shù)組名作為函數(shù)參數(shù)
在函數(shù)調(diào)用前,形參數(shù)組并不占用內(nèi)存,在函數(shù)調(diào)用的時(shí)候,形參數(shù)組并沒(méi)有另外開(kāi)辟新的存儲(chǔ)單元,而是以實(shí)參數(shù)組的首地址作為形參數(shù)組的首地址,這樣實(shí)參數(shù)組array的第1個(gè)元素和形參數(shù)組arr的第1個(gè)元素共占一個(gè)內(nèi)存單元。同理,array[1]與arr[1]共占一個(gè)內(nèi)存單元。如果在函數(shù)調(diào)用過(guò)程中使形參數(shù)組arr的元素值發(fā)生變化也就使得實(shí)參數(shù)組的元素值發(fā)生了變化。實(shí)參數(shù)組和形參數(shù)組各元素之間并不存在“值傳遞”。6.2.3數(shù)組名作為函數(shù)參數(shù)算法分析:將a[0]與a[n-1]對(duì)換,再將a[1]與a[n-2]對(duì)換,……,直到將a[(n-1)/2]與a[n-int((n-1)/2)]對(duì)換?,F(xiàn)在用循環(huán)處理這個(gè)問(wèn)題,設(shè)兩個(gè)“位置指示變量”i和j,i的初始值為0,j的初始值為n-1。將a[i]和a[j]交換,然后使i的值加1,j的值減1,再將a[i]和a[j]對(duì)換,直到i=(n-1)/2為止?!纠?.5】將數(shù)組a中n個(gè)整數(shù)按照相反順序存放。6.2.3數(shù)組名作為函數(shù)參數(shù)voidmain(){inti,a[10]={3,1,9,11,0,6,7,5,4,2};for(i=0;i<10;i++)printf("%d,",a[1]);printf("\n");inv(a,10);for(i=0;i<10;i++)printf("%d,",a[i]);printf("\n");}運(yùn)行情況如下:3,1,9,11,0,6,7,5,4,22,4,5,7,6,0,11,9,1,3#include"stdio.h"voidinv(intx[],intn){inttemp,i,j,m=(n-1)/2;for(i=0;i<m;i++){j=n-1-i;temp=x[i];x[i]=x[j];x[j]=temp;}return;}/*形參x是數(shù)組名*/6.2.3數(shù)組名作為函數(shù)參數(shù)
對(duì)這個(gè)程序可以做一些改動(dòng)。將函數(shù)inv中的形參x改為指針變量。實(shí)參為數(shù)組名a,即數(shù)組a的首地址,傳遞給形參指針變量x,x就指向a[0]。x+m是a[m]元素的地址。設(shè)i和j以及p都是指針變量,用它們指向有關(guān)元素。i的初始值為x,j的初始值為x+n-1,見(jiàn)圖6-6。使*i和*j交換就是使a[i]與a[j]交換。圖6-6指針變量與數(shù)組的關(guān)系6.2.3數(shù)組名作為函數(shù)參數(shù)voidmain(){inti,a[10]={3,7,9,11,0,6,7,5,4,2};for(i=0;i<10;i++)printf("%d,",a[1]);printf("\n");inv(a,10);for(i=0;i<10;i++)printf("%d,",a[i]);printf("\n");}【例6.6】程序如下:#include"stdio.h"voidinv(int*x,intn){intp,temp,*i,*j,m=(n-1)/2;i=x;j=x+n-1;p=x+m;for(;i<=p;i++,j--){temp=*x;*x=*j;j=temp;}return;}6.2.3數(shù)組名作為函數(shù)參數(shù)main(){inti,number[10];for(i=0;i<10;i++)scanf("%d",&number[i]);max_min_value(nember,10);printf("\nmax=%d,min=%d\n",max,min);}運(yùn)行結(jié)果如下:-567675489034-2319↙max=89,min=-23【例6.7】從10個(gè)數(shù)中找出其中最大值和最小值。算法分析:本題要求不改變數(shù)組元素的值,只須找出該數(shù)組中的最大值與最小值,而函數(shù)只能得到一個(gè)返回值,現(xiàn)在用全局變量在函數(shù)之間傳遞數(shù)據(jù)。#include"stdio.h"intmax,min;voidmax_min_value(intarray[],intn){intp,array_end;array_end=array+n;max=min=*array;for(p=array+1;p<array_end;p++)if(*p>max)max=*p;elseif(*p<min)min=*p;return;}/*全局變量*/6.2.3數(shù)組名作為函數(shù)參數(shù)程序可改為:#include"stdio.h"intmax,min;voidmax_min_value(int*array,intn){int*p,*array_end;array_end=array+n;max=min=*array;for(p=array+1;p<array_end;p++)if(*p>max)max=*p;elseif(*p<min)min=*p;return;}實(shí)參也可以不用數(shù)組名,而用指針變量傳遞地址。main(){inti,number[10],*p;p=number;for(i=0;i<10;i++)scanf("%d",p);for(p=number,i=0;i<10;i++,p++)printf("%d",*p);p=number;max_min_value(p,10);printf("\nmax=%d,min=%d\n",max,min);}6.2.3數(shù)組名作為函數(shù)參數(shù)形參用數(shù)組名、實(shí)參用指針變量。
引入指向數(shù)組的指針變量后,數(shù)組及指向數(shù)組的指針變量作函數(shù)參數(shù)時(shí),可有4種等價(jià)形式(本質(zhì)上是一種,即指針數(shù)據(jù)作函數(shù)參數(shù)):形參和實(shí)參都用數(shù)組名。形參和實(shí)參都用指針變量。形參用指針變量、實(shí)參用數(shù)組名。6.2.4指針與字符數(shù)組
在C語(yǔ)言中,既可以用字符數(shù)組表示字符串,也可以用字符指針變量來(lái)表示;引用時(shí),既可以逐個(gè)字符引用,也可以整體引用。
字符串在內(nèi)存中的起始地址稱(chēng)為字符串的指針,可以定義一個(gè)字符指針變量指向一個(gè)字符串。1.字符串的表示和引用6.2.4指針與字符數(shù)組#include"stdio.h"main(){char*string="IloveBeijing.";for(;*string!='\0';string++)printf("%c",*string);printf("\n");}也可以分成如下兩條語(yǔ)句:char*string;string="IloveBeijing.";程序運(yùn)行結(jié)果:IloveBeijing(1)逐個(gè)引用。【例6.9】使用字符指針變量表示和引用字符串。6.2.4指針與字符數(shù)組#include"stdio.h"main(){char*string="IloveBeijing.";printf("%s",*string);}(2)整體引用?!纠?.10】采用整體引用的辦法改寫(xiě)例6.9。注意:其他類(lèi)型的數(shù)組是不能用數(shù)組名來(lái)一次性輸出它的全部元素的,只能逐個(gè)元素輸出。對(duì)字符串中字符的存取可以用下標(biāo)方法,也可以用指針?lè)椒ā?.2.4指針與字符數(shù)組#include"stdio.h"main(){chara[]="HelloWorld!",b[20];inti;for(i=0;*(a+1)!='\0';i++)*(b+i)=*(a+i);*(b+i)='\0';printf("stringais:%s\n",a);printf("stringbis:");for(i=0;b[i]!='\0';i++)printf("%c",b[i]);printf("\n");}程序運(yùn)行結(jié)果為:stringais:HelloWorld!stringbis:HelloWorld!【例6.11】將字符串a(chǎn)復(fù)制到字符串b中。6.2.4指針與字符數(shù)組#include"stdio.h"main(){chara[]="HelloWorld!",b[20],*p1,*p2;inti;p1=a;p2=b;for(;*p1!='\0';p1++,p2++)*p2=*p1;*p2='\0';printf("stringais:%s\n",a);printf("stringbis:");for(i=0;b[i]!='\0';i++)printf("%c",b[i]);printf("\n");}也可以設(shè)指針變量,用其值的改變來(lái)指向字符串中不同的字符?!纠?.12】用指針變量來(lái)處理例6.11的問(wèn)題。6.2.4指針與字符數(shù)組2.字符指針變量與字符數(shù)組的比較(3)指針變量的值是可以改變的,字符指針變量也不例外。(1)存儲(chǔ)內(nèi)容不同。(2)賦值的方式不同。字符數(shù)組中存儲(chǔ)的是字符串本身。字符指針變量中存儲(chǔ)的是字符串的首地址;字符指針變量賦值語(yǔ)句:char*pointer;pointer="Thisisaexample.";charchar_array[20];char_array="Thisisaexample.";/*非法的用法*/字符數(shù)組雖然可以在定義時(shí)初始化,但不能用賦值語(yǔ)句整體賦值。6.2.4指針與字符數(shù)組charstr[]={"IloveChina!"};str=str+7;printf("%s",str);main(){char*a="IloveChina!";a=a+7;printf("%s",a);}【例6.13】利用指針字符變量輸出一串字符。程序運(yùn)行的結(jié)果為:China!下面是錯(cuò)誤的:6.2.4指針與字符數(shù)組#include"stdio.h"main(){char*a="ILOVECHINA!";inti;printf("Thesixthcharacteris%c\n",a[5]);for(i=0;a[i]!='\0';i++)printf("%c",a[i]);}【例6.14】程序運(yùn)行的結(jié)果為:ThesixthcharacterisEILOVECHINA!6.2.4指針與字符數(shù)組3.字符串指針作為函數(shù)參數(shù)#include"stdio.h"voidstring_copy(char*str_form,char*str_to){inti=0;for(;(*(str_to+i)=*(str_form+i))!='\0';i++); }main(){chararray_str1[20]="Iamateacher.";chararray_str2[20];string_copy(array_str1,array_str2); printf("array_str2=%s\n",array_str2);}【例6.15】用函數(shù)調(diào)用方式,實(shí)現(xiàn)字符串的復(fù)制。程序的運(yùn)行結(jié)果:Iamateacher./*循環(huán)體為空語(yǔ)句*//*數(shù)組名作為實(shí)參*/6.2.4指針與字符數(shù)組其特點(diǎn)是:先復(fù)制、后判斷,循環(huán)結(jié)束前,結(jié)束標(biāo)志已經(jīng)復(fù)制。
“for(;(*(str_to+i)=*(str_form+i))!='\0\;i++);”語(yǔ)句的執(zhí)行過(guò)程為:首先將源串中的當(dāng)前字符復(fù)制到目標(biāo)串中;然后判斷該字符(即賦值表達(dá)式的值)是否為結(jié)束標(biāo)志。如果不是,則相對(duì)位置變量增1,以便復(fù)制下一個(gè)字符;如果是結(jié)束標(biāo)志,則結(jié)束循環(huán)。6.2.5數(shù)組指針
它表明指針p指向的存儲(chǔ)空間有4個(gè)整型元素,即數(shù)組指針p指向一個(gè)一維數(shù)組,p的值就是該一維數(shù)組的首地址。
如果定義一個(gè)指針p,讓它指向一個(gè)包含n個(gè)元素的一維數(shù)組,且p的增值以一維數(shù)組的長(zhǎng)度為單位,此時(shí),如果指針p指向二維數(shù)組的某一行,則p+1就指向了該二維數(shù)組的下一行。在C++中,這樣的指針?lè)Q為數(shù)組指針,使用數(shù)組指針可以很方便地處理二維數(shù)組。數(shù)組指針的說(shuō)明形式如下:存儲(chǔ)類(lèi)型數(shù)據(jù)類(lèi)型(*指針名)[元素個(gè)數(shù)]例如:在程序中定義一個(gè)數(shù)組指針:int(*p)[4];6.2.5數(shù)組指針(2)p是一個(gè)行指針,它只能指向一個(gè)包含n個(gè)元素的一維數(shù)組,不能指向一維數(shù)組中的元素,如果要訪問(wèn)一維數(shù)組中的某個(gè)元素,如第j個(gè)元素,可用(*p)[j]表示。在使用數(shù)組指針時(shí),有兩點(diǎn)一定要注意:(1)*p兩側(cè)的括號(hào)一定不能漏掉,如果寫(xiě)成*p[4]的形式,由于[]的運(yùn)算級(jí)別高,因此p先和[4]結(jié)合,是數(shù)組,然后再與前面的*結(jié)合,*p[4]是指針數(shù)組。6.2.5數(shù)組指針#include"stdio.h"voidmain(){inta[2][3]={1,3,5,7,9,11};int(*p)[3];inti,j;for(i=0;i<2;i++){for(j=0;j<3;j++)printf("%2d",(*p)[i]);p++;}}【例6.16】用數(shù)組指針處理二維數(shù)組。程序的運(yùn)行結(jié)果為:13579116.3指針與函數(shù)
函數(shù)之間可以傳遞一般變量的值,也可以傳遞地址(指針)。函數(shù)與指針之間有著密切的關(guān)系,它包含3種含義:指針作為函數(shù)的參數(shù),函數(shù)的返回值為指針以及指向函數(shù)的指針。6.3.1指針作函數(shù)參數(shù)指針變量,既可以做函數(shù)的形參,也可以作函數(shù)的實(shí)參。指針變量作實(shí)參時(shí),與普通變量一樣,也是“值傳遞”,即將指針變量的值(一個(gè)地址)傳遞給被調(diào)用函數(shù)的形參(必須是一個(gè)指針變量)。6.3.1指針作函數(shù)參數(shù)#include"stdio.h"voidexchange(int*pointer1,int*pointer2){inttemp;temp=*pointer1;*pointer1=*pointer2;*pointer2=temp;}voidmain(){intnum1,num2;int*num1_p=&num1,*num2_p=&num2;printf("Inputthefirstnumber:");scanf("%d",num1_p);printf("Inputthesecondnumber:");scanf("%d",num2_p);printf("num1=%d,num2=%d\n",num1,num2);if(*num1_p>*num2_p)exchange(num1_p,num2_p);printf("min=%d,max=%d\n",num1,num2);}程序的運(yùn)行情況如下:Inputthefirstnumber:9↙Inputthesecondnumber:6↙num1=9,num2=6min=6,max=9【例6.17】使用函數(shù)調(diào)用方式改寫(xiě)例6.2,要求實(shí)參為指針變量。/*定義并初始化指針變量num1_p和num2_p*//*即num1>num2*//*指針變量作實(shí)參*//*輸出排序后的num1和num2的值*/6.3.1指針作函數(shù)參數(shù)
其機(jī)制為:在執(zhí)行被調(diào)用函數(shù)時(shí),使形參指針變量所指向的變量的值發(fā)生變化;函數(shù)調(diào)用結(jié)束后,通過(guò)不變的實(shí)參指針(或?qū)崊⒅羔樧兞浚⒆兓闹当A粝聛?lái)。雖然被調(diào)用函數(shù)不能改變實(shí)參指針變量的值,但可以改變它們所指向的變量的值。為了利用被調(diào)用函數(shù)改變的變量值,應(yīng)該使用指針(或指針變量)作函數(shù)實(shí)參。6.3.1指針作函數(shù)參數(shù)/*排序*/if(num1<num2)exchange(&num1,&num2);if(num1<num3)exchange(&num1,&num3);if(num2<num3)exchange(&num2,&num3);/*輸出排序結(jié)果*/printf("排序結(jié)果:%d,%d,%d\n",num1,num2,num3);}【例6.18】輸入3個(gè)整數(shù),按降序(從大到小的順序)輸出。要求使用變量的指針作函數(shù)調(diào)用的實(shí)參來(lái)實(shí)現(xiàn)。#include"stdio.h"voidexchange(int*pointer1,int*pointer2){inttemp;temp=*pointer1;*pointer1=*pointer2;*pointer2=temp;}voidmain(){intnum1,num2,num3;/*從鍵盤(pán)上輸入3個(gè)整數(shù)*/printf("Inputthefirstnumber:");scanf("%d",num1);printf("Inputthesecondnumber:");scanf("%d",num2);printf("Inputthethirdnumber:");scanf("%d",num3);printf("num1=%d,num2=%d,num3=%d",num1,num2,num3)程序的運(yùn)行情況如下:Inputthefirstnumber:9↙Inputthesecondnumber:6↙Inputthethirdnumber:12↙num1=9,num2=6,num3=12排序結(jié)果:12,9,66.3.2函數(shù)指針1.函數(shù)指針的概念
一個(gè)函數(shù)在編譯時(shí)被分配了一個(gè)入口地址,這個(gè)地址就稱(chēng)為該函數(shù)的指針。可以用一個(gè)指針變量指向一個(gè)函數(shù),然后通過(guò)該指針變量調(diào)用此函數(shù)。6.3.2函數(shù)指針#include"stdio.h"voidmain(){intmax();int(*p)();inta,b,c;p=max;scanf("%d,%d",&a,&b);c=(*p)(a,b);printf("a=%d,b=%d,max=%d",a,b,c);}intmax(intx,inty){intz;if(x>y)z=x;elsez=y;return(z);}【例6.19】求a和b中的大者。6.3.2函數(shù)指針注意:對(duì)指向函數(shù)的指針變量,諸如p+i、p++∕p--等運(yùn)算是沒(méi)有意義的。2.指向函數(shù)的指針變量(1)定義格式:函數(shù)類(lèi)型(*指針變量)();注意:“(*指針變量)”外的括號(hào)不能缺,否則就成了返回指針值的函數(shù)。例如:int(*fp)();/*fp為指向int函數(shù)的指針變量*∕(2)賦值。函數(shù)名代表該函數(shù)的入口地址。
可用函數(shù)名給指向函數(shù)的指針變量賦值。指向函數(shù)的指針變量=[&]函數(shù)名;注意:函數(shù)名后不能帶括號(hào)和參數(shù);函數(shù)名前的“&”符號(hào)是可選的。(3)調(diào)用格式:(*函數(shù)指針變量)([實(shí)參表])
函數(shù)名作實(shí)參時(shí),因?yàn)橐笔±ㄌ?hào)和參數(shù),造成編譯器無(wú)法判斷它是一個(gè)變量還是一個(gè)函數(shù),所以必須加以說(shuō)明。6.3.2函數(shù)指針
指向函數(shù)的指針變量的常用用途之一就是將函數(shù)指針作參數(shù)傳遞到其他函數(shù)。3.指向函數(shù)的指針變量作函數(shù)參數(shù)6.3.2函數(shù)指針【例6.20】設(shè)一個(gè)函數(shù)process,在調(diào)用它時(shí),每次實(shí)現(xiàn)不同的功能。輸入a和b兩個(gè)數(shù),第一次調(diào)用process時(shí)找出a和b中大者,第二次找出其中小者,第三次求a和b之和。#include"stdio.h"main(){intmax(int,int); intmin(int,int); intadd(int,int); inta,b;scanf("%d,%d",&a,&b);printf("max=");processs(a,b,max);printf("min=");process(a,b,min);printf("sum=");process(a,b,add);}/*函數(shù)聲明*//*函數(shù)聲明*//*函數(shù)聲明*/6.3.2函數(shù)指針max(intx,inty) {intz;if(x>y)z=x;elsez=y;return(z);}min(intx,inty) {intz;if(x<y)z=x;elsez=y;return(z);}add(intx,inty) {intz;z=x+y;return(z);}process(intx,inty,int(*fun)(int,int)){intresult;result=(*fun)(x,y);printf("%d\n",result);}程序運(yùn)行結(jié)果如下:3,9↙max=9min=3sum=12/*表示fun是指向函數(shù)的指針,該函數(shù)是一個(gè)整型函數(shù),有兩個(gè)整型形參*//*函數(shù)定義*//*函數(shù)定義*//*函數(shù)定義*/6.3.3指針函數(shù)pr是函數(shù)名,調(diào)用它以后能得到一個(gè)指向整型數(shù)據(jù)的指針(地址)。x、y是函數(shù)pr的形參。
在*pr兩側(cè)沒(méi)有括號(hào),在pr的兩側(cè)分別為*運(yùn)算符和()運(yùn)算符。而()的優(yōu)先級(jí)高于*,因此pr先與()結(jié)合。顯然這是函數(shù)形式。這個(gè)函數(shù)前面有一個(gè)*,表示此函數(shù)是指針型函數(shù)(函數(shù)值是指針)。最前面的int表示返回的指針指向整型變量。
指針函數(shù)是指返回值為指針的函數(shù),函數(shù)的返回值可以是不同類(lèi)型的指針。指針函數(shù)定義格式:函數(shù)類(lèi)型*函數(shù)名([形參表])例如:int*pr(x,y);注意:6.3.3指針函數(shù)int*seek(int(*pnt_row)[3]){inti=0,*pnt_col; pnt_col=*(pnt_row+1); for(;i<3;i++)if(*(*pnt_row+i)<60){pnt_col=*pnt_row; break;}return(pnt_col);}【例6.21】某數(shù)理化三項(xiàng)競(jìng)賽訓(xùn)練組有3個(gè)人,找出其中至少有一項(xiàng)成績(jī)不合格者。要求使用指針函數(shù)實(shí)現(xiàn)。/*定義一個(gè)(列)指針變量pnt_col*//*使pnt_col指向下一行之首(作標(biāo)志用)*//*某項(xiàng)成績(jī)不合格*//*使pnt_col指向本行之首*//*退出循環(huán)*/6.3.3指針函數(shù)程序運(yùn)行結(jié)果:No.1gradelist:556575main(){intgrade[3][3]={{55,65,75},{65,75,85},{75,80,90}};inti,j,*pointer; for(i=0;i<3;i++) {pointer=seek(grade+i); if(pointer==*(grade+i)) {printf("No.℅dgradelist:",i+1);for(j=0;j<3;j++)printf("℅d",*(pointer+j));printf("\n");}}}
/*定義一個(gè)(列)指針變量pointer*//*控制每個(gè)學(xué)生*//*用行指針作實(shí)參,調(diào)用seek()函數(shù)*//*該學(xué)生至少有一項(xiàng)成績(jī)不合格*//*輸出該學(xué)生的序號(hào)和各項(xiàng)成績(jī)*/6.3.3指針函數(shù)if(*(*pnt_row+i)<60)行中的pnt_row是一個(gè)行指針,指向數(shù)組grade的第i行;*pnt_row使指針由行轉(zhuǎn)換為列,指向數(shù)組grade的第i行第0列;*pnt_row+j的值還是一個(gè)指針,指向數(shù)組的第i行第j列;*(*pnt_row+j)是一個(gè)數(shù)據(jù)(數(shù)組元素grade[i][j]的值)。程序說(shuō)明如下:(1)主函數(shù)中的pointer=seek(grade+i);語(yǔ)句調(diào)用seek()函數(shù)時(shí),將實(shí)參grade+i(行指針)的值復(fù)制到形參pnt_row(行指針變量)中,使形參pnt_row指向grade數(shù)組的第i行。pnt_col=*(pnt_row+1);語(yǔ)句中的*(pnt_row+1)將行指針轉(zhuǎn)換為列指針,指向grade數(shù)組的第i+1行第0列,并賦值給(列)指針變量pnt_col。(2)在指針函數(shù)seek()中:6.4.1多級(jí)指針
使指針p指向a,則指針p所指向的變量*p就是要處理的數(shù)據(jù)變量a。如果同時(shí)存在另一個(gè)指針pp,并且把指針p的地址賦予指針變量pp,即:pp=&p;,則pp就指向指針p,這時(shí)指針pp所指向的變量*pp就是指針p,pp就是一個(gè)二級(jí)指針。數(shù)據(jù)類(lèi)型**指針變量[,**指針變量2,…];1.概念
一個(gè)指針變量可以指向一個(gè)相應(yīng)數(shù)據(jù)類(lèi)型的數(shù)據(jù),例如:inta,*p;p=&a;2.定義格式6.4.1多級(jí)指針#include"stdio.h"main(){staticchar*name[]={"Followme","BASIC","FORTRAN","GreatWall","Computerdesign"};char**p;inti;for(i=0;i<5;i++){p=name+i;printf("%s\n",*p);}}程序運(yùn)行結(jié)果如下:FollowmeBASICFORTRANGreatWallComputerdesign【例6.22】用二級(jí)指針處理多個(gè)字符串。6.4.1多級(jí)指針
此時(shí)為了得到數(shù)據(jù)“5”,可以先使p=num+2,然后輸出**p。注意*p是p間接指向的對(duì)象地址。而**p是p間接指向的對(duì)象的值。指針數(shù)組的元素也可以不指向字符串,而指向整型數(shù)據(jù)或浮點(diǎn)型數(shù)據(jù)等。例如:inta[5]={1,3,5,7,9};int*num[5]={&a[0],&a[1],&a[2],&a[3],&a[4]};int**p;6.4.2指針數(shù)組
表示定義一個(gè)由5個(gè)指針變量構(gòu)成的指針數(shù)組,數(shù)組中的每個(gè)數(shù)組元素——指針,都指向一個(gè)整數(shù)。1.概念
數(shù)組的每個(gè)元素都是一個(gè)指針數(shù)據(jù)。指針數(shù)組比較適合用于指向多個(gè)字符串,使字符串處理更加方便、靈活。2.定義格式數(shù)據(jù)類(lèi)型*數(shù)組名[元素個(gè)數(shù)]例如:int*pa[5];6.4.2指針數(shù)組int(*pb)[5]表示定義了一個(gè)指向數(shù)組的指針pb,pb指向的數(shù)組是一維的,大小為5的整型數(shù)組,其結(jié)構(gòu)如下所示。int*pa[5]與int(*pb)[5]的區(qū)別:int*pa[5]int(*pb)[5]6.4.2指針數(shù)組#include"stdio.h"voidsort(char*name[],intcount){char*temp_p;inti,j,min;/*使用選擇法排序*/for(i=0;i<count-1;i++) /*外循環(huán):控制選擇次數(shù)*/{min=i; /*預(yù)置本次最小串的位置*/for(j=i+1;j<count;j++) /*內(nèi)循環(huán):選出本次的最小串*/if(strcmp(name[min],name[j])>0) /*存在更小的串*/min=j; /*保存之*/if(min!=i) /*存在更小的串,交換位置*/{temp_p=name[i];name[min];name[min]=temp_p;}}}【例6.23】有若干計(jì)算機(jī)圖書(shū),請(qǐng)按字母順序從小到大輸出書(shū)名。使用排序函數(shù)完成排序,在主函數(shù)中進(jìn)行輸入輸出。6.4.2指針數(shù)組/*主函數(shù)main()*/main(){char*name[5]={"BASIC","FORTRAN","PASCAL","C","FoxBASE"};inti=0;
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年度國(guó)有企業(yè)員工持股計(jì)劃合同模板2篇
- 二零二五年度高新技術(shù)產(chǎn)業(yè)園區(qū)建設(shè)貸款擔(dān)保合同3篇
- 二零二五年度布草行業(yè)供應(yīng)鏈金融解決方案合同3篇
- 2025年度教育機(jī)構(gòu)場(chǎng)地租賃合同終止及教學(xué)資源共享協(xié)議4篇
- 2024版區(qū)域公司運(yùn)營(yíng)合作合同版B版
- 貨幣金融學(xué):第1章 貨幣與貨幣制度
- 2025年度企業(yè)年會(huì)場(chǎng)地借用及服務(wù)保障合同范本3篇
- 個(gè)人機(jī)械租賃協(xié)議書(shū)(2024版)
- 2024資金擔(dān)保協(xié)議范本
- 專(zhuān)業(yè)木工班組2024年施工分包合同
- C及C++程序設(shè)計(jì)課件
- 帶狀皰疹護(hù)理查房
- 公路路基路面現(xiàn)場(chǎng)測(cè)試隨機(jī)選點(diǎn)記錄
- 平衡計(jì)分卡-化戰(zhàn)略為行動(dòng)
- 國(guó)家自然科學(xué)基金(NSFC)申請(qǐng)書(shū)樣本
- 幼兒教師干預(yù)幼兒同伴沖突的行為研究 論文
- 湖南省省級(jí)溫室氣體排放清單土地利用變化和林業(yè)部分
- 材料設(shè)備驗(yàn)收管理流程圖
- 培訓(xùn)機(jī)構(gòu)消防安全承諾書(shū)范文(通用5篇)
- (完整版)建筑業(yè)10項(xiàng)新技術(shù)(2017年最新版)
- 第8期監(jiān)理月報(bào)(江蘇版)
評(píng)論
0/150
提交評(píng)論