版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
第八章指針31、園日涉以成趣,門雖設(shè)而常關(guān)。32、鼓腹無所思。朝起暮歸眠。33、傾壺絕余瀝,窺灶不見煙。34、春秋滿四澤,夏云多奇峰,秋月?lián)P明輝,冬嶺秀孤松。35、丈夫志四海,我愿不知老。第八章指針第八章指針31、園日涉以成趣,門雖設(shè)而常關(guān)。32、鼓腹無所思。朝起暮歸眠。33、傾壺絕余瀝,窺灶不見煙。34、春秋滿四澤,夏云多奇峰,秋月?lián)P明輝,冬嶺秀孤松。35、丈夫志四海,我愿不知老。第八章指針指針是C語(yǔ)言的一個(gè)重要概念,也是C語(yǔ)言的一個(gè)重要特色。深刻理解和正確使用指針是學(xué)習(xí)本章的基本要求。本章是一個(gè)難點(diǎn),也是一個(gè)重點(diǎn),初學(xué)者不易掌握。在理解和熟悉基本內(nèi)容的前提下,上機(jī)實(shí)驗(yàn)是必不可少的環(huán)節(jié)。8.1指針的概念二、舉例
如有定義:charc=‘A’;inta=3;則所占內(nèi)存情況如下:注意:c和a的地址可能相鄰,也可能不相鄰,是由系統(tǒng)分配的,我們不用關(guān)心。118.1指針的概念三、指針與指針變量1、指針:簡(jiǎn)單地說,指針就是地址。二者是同一個(gè)概念的兩種說法。只不過指針更形象一些,就像一個(gè)針一樣,可以指向某個(gè)內(nèi)存單元。2、指針變量:首先指針變量就是一個(gè)變量,和我們以前所講的其它變量沒有本質(zhì)區(qū)別。不同之處在于這種變量中所存放的內(nèi)容是地址。什么是指針變量呢?我們回憶一下什么叫整型變量例如:先定義了某整型變量a,再定義一個(gè)指針變量b,將變量a的內(nèi)存地址賦給指針變量b,即b=&a;這就代表指針b指向變量a。打個(gè)比方8.1指針的概念四、直接訪問和間接訪問有兩個(gè)上鎖且放著物品的盒子A、B,如果你有A盒子的鑰匙,則可以直接打開A盒子將物品取出;如果你有B盒子的鑰匙,而A盒子的鑰匙在B盒子中,要想取出A盒子中的物品,則必須先打開B盒子,取出A盒子的鑰匙,再打開A盒子將物品取出。上面兩種情況就是直接訪問和間接訪問的概念。8.1指針的概念1、直接訪問通過變量本身對(duì)變量進(jìn)行存取的方式,稱為直接訪問。如定義:intx;則x=10;x+=5;等等這種訪問方式只需要變量本身就得到了該變量的全部信息,不需要其它內(nèi)容,是直接的。2、間接訪問通過指針變量實(shí)現(xiàn)對(duì)變量的訪問方式,稱為間接訪問。首先要定義一個(gè)指針變量,然后將一個(gè)同類型變量的地址賦給該指針變量(這時(shí)我們稱指針變量指向該變量),這樣就可以進(jìn)行間接訪問了。間接訪問的過程是:由指針變量得到變量的地址,根據(jù)該地址找到變量的存儲(chǔ)區(qū),再對(duì)該存儲(chǔ)區(qū)的內(nèi)容進(jìn)行存取,從而實(shí)現(xiàn)了對(duì)變量的間接訪問。例如:inta,*p;p=&a;*p=6;/*相當(dāng)于a=6;*/printf(“%d”,*p);該節(jié)結(jié)束,返回目錄*p相當(dāng)于變量a8.2指針變量的定義和引用一、指針變量的定義和賦值1、格式:類型名*指針變量名;2、舉例int*p1;char*s1,*s2;float*a1,*a2,f;3、說明a.類型名:指針變量所指向的變量類型。b.*是定義指針變量的標(biāo)志,不可丟掉。c.指針變量定義后,其值是不確定的。8.2指針變量的定義和引用4、賦值:可以進(jìn)行初始化,也可以使用賦值語(yǔ)句(1)、初始化:inta,*s=&a;int*f=NULL;(2)、賦值語(yǔ)句inta,*s;s=&a;說明:
a、“&”代表取地址運(yùn)算符,&a代表變量a的地址,&a是一個(gè)指針常量,可為一個(gè)指針變量賦值。b、還可將數(shù)組名和函數(shù)名賦給某些類型的指針變量,因?yàn)閿?shù)組名和函數(shù)名代表相應(yīng)的起始地址。不定8.2指針變量的定義和引用在分析有關(guān)指針的程序時(shí),畫圖是很好的方法:若有:inta,*s;則sa若有:inta=5,*s=&a;則不定5&a8.2指針變量的定義和引用c、注意:只能用同類型變量的地址進(jìn)行賦值!如定義:int*s;floatf;則s=&f;是非法的。d、不能給指針變量賦以整型量或其它地址量。如:int*p;則p=2000;是錯(cuò)誤的。8.2指針變量的定義和引用二、指針變量的引用1、兩個(gè)運(yùn)算符:&與*
&:取地址,注意與作位運(yùn)算符時(shí)的不同(雙目)
*:指針運(yùn)算符(間接訪問符),取存儲(chǔ)單元的內(nèi)容,*P表示P所指向的變量,注意與乘運(yùn)算符不同。2、說明a.&既可作用于一般變量,也可作用于指針變量b.*只能作用于指針變量,*s等同于變量a。c.定義指針變量時(shí)的*與該處的含義不同8.2指針變量的定義和引用3、指針變量可以進(jìn)行的操作(1)賦值:inta,*p1=&a,*p2;p2=p1;(2)輸出:printf(“%x”,p1);(3)增減:p1++;p2--;p1+=4;(只能和一個(gè)整數(shù))(4)取內(nèi)容:*p1=5;a=5;printf(“%d”,*p1);(5)比較:一般與指針常量NULL進(jìn)行比較;兩指針變量值的大小比較無意義。表示空指針,即不指向任何單元,在頭文件stdio.h中定義。是指撥一個(gè)變量的位置,并非地址值簡(jiǎn)單加1。8.2指針變量的定義和引用例8.1
#include<stdio.h>
main()
{
inta1=11,a2=22;
int*p1,*p2;
p1=&a1;
p2=&a2;
printf(“%d,%d\n”,*p1,*p2);
p2=p1;
printf(“%d,%d\n”,*p1,*p2);
}舉例p1&a11122a1p2a2&a2*p1*p2&a1運(yùn)行結(jié)果如下:
11,2211,11*p2*p28.2指針變量的定義和引用例8.2
#include<stdio.h>
main()
{
inta1=11,a2=22;
int*p1,*p2,*p;
p1=&a1;
p2=&a2;
printf(“%d,%d\n”,*p1,*p2);
p=p1;p1=p2;p2=p;
printf(“%d,%d\n”,*p1,*p2);
}p1&a11122a1p2a2&a2&a1&a2舉例運(yùn)行結(jié)果如下:
11,2222,118.2指針變量的定義和引用例8.3
#include<stdio.h>
main()
{
inta1=11,a2=22,t;
int*p1,*p2;
p1=&a1;
p2=&a2;
printf(“%d,%d\n”,a1,a2);
t=*p1;*p1=*p2;*p2=t;
printf(“%d,%d\n”,a1,a2);
}p1&a11122a1p2a2&a2*p1*p22211舉例運(yùn)行結(jié)果如下:
11,2222,118.2指針變量的定義和引用三、指針作為函數(shù)的參數(shù)1、形式:只需要形式參數(shù)名前加上一個(gè)*即可。如:voidtest(int*pointer,charf,char*s)2、說明參數(shù)的傳遞是值傳遞,單向的(從實(shí)參到形參)。這樣改變形參的值不改變實(shí)參的值。通過指針作為參數(shù)可以將主調(diào)函數(shù)中某變量的地址傳遞到被調(diào)函數(shù)中,從而可以改變?cè)摰刂穼?duì)應(yīng)變量的值,即改變主調(diào)函數(shù)中局部變量的值。但如果形參本身改變了,其值不會(huì)傳給實(shí)參。即形參指針的值改變了,不會(huì)影響實(shí)參指針的地址值。8.2指針變量的定義和引用11實(shí)參a函數(shù)調(diào)用形參b11調(diào)用結(jié)束11實(shí)參a函數(shù)調(diào)用形參*p調(diào)用結(jié)束15傳遞地址&a22普通變量參數(shù)傳遞指針類型參數(shù)傳遞8.2指針變量的定義和引用例8.4:#include<stdio.h>
voidtest(int*pt);
main()
{inta=11,*p=&a;
printf(“beforecall,a=%d,p=%x\n”,a,p);
test(p);
printf(“aftercall,a=%d,p=%x\n”,a,p);
}
voidtest(int*pt)
{*pt=22;pt++;printf(“pointer=%x”,pt);}執(zhí)行test(&a)返回8.2指針變量的定義和引用11實(shí)參a形參*ptpt++22指針類型參數(shù)傳遞實(shí)參p=&a&a編一函數(shù),找出一維數(shù)組中的最大值和最小值。例8.5復(fù)習(xí)指針變量:是一種特殊的變量,存放的是其它變量的地址,如:inta,*p=&a;此時(shí)指針p就指向了變量a,就可以用指針p對(duì)變量a進(jìn)行間接訪問,即*p等價(jià)于a;指針作為函數(shù)參數(shù):如希望函數(shù)調(diào)用結(jié)束后,主調(diào)函數(shù)中實(shí)參變量的值改變,或希望通過指針參數(shù)將函數(shù)中的結(jié)果傳遞給主調(diào)函數(shù),此時(shí)形參應(yīng)定義成指針類型,函數(shù)調(diào)用時(shí)用某變量的地址或指向該變量的指針作為實(shí)參調(diào)用。例如a的地址編號(hào):ffd9………………p的地址編號(hào):ffe211011001111111110000010100000000分清幾種含義:printf(“%d”,p);printf(“%d”,*p);printf(“%d”,a);printf(“%d”,&a);printf(“%d”,&p);8.3指針與一維數(shù)組在C語(yǔ)言中,指針與數(shù)組有著密切的關(guān)系。對(duì)數(shù)組元素,既可以采用數(shù)組下標(biāo)來引用,也可以通過指向數(shù)組元素的指針來引用。采用指針方法處理數(shù)組,可以產(chǎn)生代碼長(zhǎng)度小、運(yùn)行速度快的程序。8.3指針與一維數(shù)組一、通過指針訪問一維數(shù)組1、數(shù)組結(jié)構(gòu)的分析設(shè)有數(shù)組定義為:inta[5];則有:(1)a表示數(shù)組在內(nèi)存中的首地址,也就是數(shù)組中第0個(gè)元素a[0]的地址,其值由系統(tǒng)在編譯時(shí)確定,程序運(yùn)行期間不能改變,所以它是一個(gè)地址常量,即指針常量,所以*a就代表第0個(gè)元素a[0]。(2)數(shù)組中的各元素按順序存放,表示為:
a[0]、a[1]、a[2]、a[3]、a[4]8.3指針與一維數(shù)組(3)數(shù)組中的各元素的地址表示為:
&a[0]、&a[1]、&a[2]、&a[3]、&a[4]或者是:a+0(或a)、a+1、a+2、a+3、a+4(4)另一種解釋:數(shù)組名是基地址,下標(biāo)是偏移量,a[i]就表示以a為基地址,偏移i個(gè)元素的那個(gè)元素。所以a[i]的地址可表示為a+i;a+i就是指向第i個(gè)元素的指針常量,所以*(a+i)代表第i個(gè)元素a[i]。所以數(shù)組各元素也可表示為:*(a+0)(或*a)、*(a+1)、*(a+2)、*(a+3)、*(a+4)注意:所謂的偏移量是偏移一個(gè)元素的位置,并非是原指針值+1,例如一個(gè)整型數(shù)組的一個(gè)偏移量應(yīng)該是兩個(gè)字節(jié),如數(shù)組a的首地址是2002單元,則a+1的值應(yīng)是2004單元。8.3指針與一維數(shù)組這樣,下標(biāo)表達(dá)式a[i]和指針表達(dá)式*(a+i)都表示數(shù)組下標(biāo)為i的元素;a+i和&a[i]都表示下標(biāo)為i的元素的地址。數(shù)組元素,即可通過下標(biāo)法直接訪問,也可通過指針變量間接訪問。使用指針變量訪問數(shù)組,可通過使指針變量的加減運(yùn)算使其指向數(shù)組的各個(gè)元素,從而遍歷數(shù)組各元素。轉(zhuǎn)8.3指針與一維數(shù)組2、指針與數(shù)組的關(guān)系現(xiàn)定義一個(gè)指針變量:int*s;并進(jìn)行賦值:s=a;或s=&a[0];則,指針變量s指向了數(shù)組a的開始,二者產(chǎn)生了聯(lián)系,這樣就可以通過指針變量s訪問數(shù)組a了。a[0]a[1]a[2]a[3]a[4]a&a[0]&a[1]&a[2]&a[3]&a[4]ss++8.3指針與一維數(shù)組當(dāng)然,對(duì)s也可以進(jìn)行其它賦值,如:s=a+2;或s=&a[2];圖變?yōu)椋篴[0]a[1]a[2]a[3]a[4]a&a[0]&a[1]&a[2]&a[3]&a[4]s說明:若進(jìn)行操作s=a;s+=2;效果與上述相同。8.3指針與一維數(shù)組當(dāng)一個(gè)指針變量指向數(shù)組的首地址,即inta[5],*p;p=a;就可用p訪問數(shù)組,*p就表示p所指向的數(shù)組元素,p+i表示p指向的當(dāng)前元素向下的第i個(gè)元素的地址,*(p+i)就表示這個(gè)元素,與下標(biāo)運(yùn)算p[i]是等價(jià)的。所以a[i],*(a+i),p[i],*(p+i)都表示數(shù)組的第i個(gè)元素,a+i,&a[i],p+i,&p[i]都表示數(shù)組的第i個(gè)元素的地址。數(shù)組名a與指針變量p的區(qū)別在于:a是指針常量,而p是指針變量,p的值可以改變,而a的值不能變,如a++或a=a+2都是非法的,而p++是合法的。8.3指針與一維數(shù)組數(shù)組inta[5]指向數(shù)組元素的指針數(shù)組元素的訪問a,&a[0],p,&p[0]a+1,&a[1],p+1,&p[1]a+i,&a[i],p+i,&p[i]a[0],*a,p[0],*pa[1],*(a+1),p[1],*(p+1)a[i],*(a+i),p[i],*(p+i)使用指針訪問數(shù)組元素的真正意義在于通過指針變量的加減訪問數(shù)組的各個(gè)元素,如指針p指向數(shù)組的首地址,在循環(huán)程序中可進(jìn)行p++運(yùn)算,通過*p訪問數(shù)組的各元素。如以下程序段:
inta[5]={1,3,5,7,9},*p;for(p=a;p<a+5;p++)printf(“%d”,*p);3、一維數(shù)組的訪問例8.6用多種方法訪問一維數(shù)組各元素
#include<stdio.h>
main()
{inta[5]={1,3,5,7,9},i,*p=a;
for(i=0;i<5;i++)printf(“%d”,a[i]);第一種方法,最直觀
for(i=0;i<5;i++)printf(“%d”,*(a+i));第二種方法
for(i=0;i<5;i++)printf(“%d”,p[i]);第三種方法
for(i=0;i<5;i++)printf(“%d”,*(p+i));第四種方法
for(;p<a+5;p++)printf(“%d”,*p);第五種方法,最有效
p=a;while(p<a+5){printf(“%d”,*p);p++;}第六種方法
p=a;while(p<a+5)printf(“%d”,*p++);第七種方法}注意:此處不能是p<=a+5使用指針訪問數(shù)組元素,應(yīng)特別注意指針變量的當(dāng)前指向,尤其是循環(huán)結(jié)束后,如:
for(;p<a+5;p++)printf(“%d”,*p);循環(huán)結(jié)束后p的值是a+5,而數(shù)組a的最后一個(gè)元素的地址是a+4,即此時(shí)p已指向數(shù)組外了,如果不重新為p賦值,直接引用*p將產(chǎn)生不可預(yù)料的后果。此種錯(cuò)誤隱蔽性強(qiáng),編譯器不指出。8.3指針與一維數(shù)組4、幾個(gè)表達(dá)式的分析設(shè)定義:inta[3]={1,2,3},*s=a;s,*sa,*as++,*s++,a++,*a++*(s++),(*s)++*(a++),(*a)++表達(dá)式*(s++)與*s++是等價(jià)的,都是先取出值,再使指針向下?lián)?個(gè)位置。(*s)++表示使當(dāng)前指向的變量值加1。初始化時(shí)的*s=a;與語(yǔ)句*s=a;的不同×××返回例題用指針的方法完成,將數(shù)組中的最小的數(shù)與第一個(gè)數(shù)對(duì)換,把最大的數(shù)與最后一個(gè)數(shù)對(duì)換。8.3指針與一維數(shù)組二、通過指針在函數(shù)間傳遞一維數(shù)組1、函數(shù)的定義形式例如:intfunc(intarray[],intn)
{函數(shù)體;}也可以寫為:intfunc(int*array,intn)
{函數(shù)體;}8.3指針與一維數(shù)組2、函數(shù)的說明形式如有函數(shù)定義:
intfunc(intarray[],intn)
{函數(shù)體;}則對(duì)該函數(shù)的說明形式可以寫為:intfunc(intarray[],intn);intfunc(int*array,intn);intfunc(int[],int);intfunc(int*,int);intfunc(intarray[],intn)函數(shù)的形參是數(shù)組(指針),函數(shù)調(diào)用時(shí)可以用數(shù)組名作為實(shí)參,從便于理解的角度可認(rèn)為形參數(shù)組與實(shí)參數(shù)組具有相同的起始地址,共占一段內(nèi)存。而實(shí)際上形參是一個(gè)指針變量,調(diào)用時(shí)將實(shí)參數(shù)組的首地址賦給該指針變量,從而使該指針變量指向?qū)崊?shù)組的第0個(gè)元素。如:func(a,5);因此,在函數(shù)內(nèi)部可用指針arry間接訪問數(shù)組a,如:while(arry<a+n)*arry++=2;注意:作為形參定義的數(shù)組名是一個(gè)指針變量,它在函數(shù)體中值可以變化,而函數(shù)內(nèi)部定義的數(shù)組,其數(shù)組名是指針常量,其值不能改變,如。既然調(diào)用的實(shí)參是某一地址,也可以是數(shù)組中任意元素的地址,如將第3個(gè)元素的地址作為實(shí)參調(diào)用也可以,此時(shí)后面的參數(shù)將加以調(diào)整,如:func(a+2,3);8.3指針與一維數(shù)組例8.7編寫在數(shù)組的最后一個(gè)元素中存放其它元素和
的函數(shù)
#include<stdio.h>
voidsummary(int*p,intn);
main()
{staticinta[11]={1,2,3,4,5,6,7,8,9,10};
summary(a,10);
printf(“Sumis%d\n”,a[10]);
}
voidsummary(int*p,intn)
{
ints=0,i=0;;
while(i<n){s+=*p++;i++;}*p=s;
}該節(jié)結(jié)束,返回目錄函數(shù)還可寫為:
voidsummary(intarr[],intn)
{inti,s=0;
for(i=0;i<n;i++)s+=arr[i];
arr[n]=s;}8.4指針與字符串字符串是一種特殊的一維數(shù)組,所以上節(jié)中介紹的方法同樣適用于對(duì)字符串的訪問。字符串的特殊性在于:字符串長(zhǎng)度任意,末尾的結(jié)束標(biāo)志是‘\0’,所以訪問字符串時(shí)常用結(jié)束標(biāo)志進(jìn)行判斷。8.4指針與字符串一、通過指針訪問字符串1、字符串結(jié)構(gòu)的分析設(shè)有數(shù)組定義為:chars[]=“abcde”;則s是一個(gè)字符數(shù)組,它里面存放的是一個(gè)字符串。它在內(nèi)存中占用6個(gè)字節(jié),但字符串長(zhǎng)度為5。其結(jié)構(gòu)為:‘a(chǎn)’‘b’‘c’‘d’‘e’‘\0’ss[0]s[1]s[2]s[3]s[4]s[5]結(jié)束標(biāo)志8.4指針與字符串字符串還可以定義為:char*s=“abcde”;它在內(nèi)存中占用6個(gè)字節(jié),長(zhǎng)度為5。其結(jié)構(gòu)為:‘a(chǎn)’‘b’‘c’‘d’‘e’‘\0’ss[0]s[1]s[2]s[3]s[4]s[5]結(jié)束標(biāo)志8.4指針與字符串2、用字符數(shù)組與用指針使用字符串的比較定義及初始化
chars[]=“abcde”;char*p=“abcde”;賦值
chars[6];char*p,b[20];
s=“abcde”;/*不對(duì)*/
p=“abcde”;p=b;
strcpy(s,“abcde”);strcpy(p,“abcde”);使用
s不能加/減,s++;p可以加/減,p++;注意:chars[]=“abc”;與chars[]={‘a(chǎn)’,’b’,’c’};的區(qū)別補(bǔ)充:如果定義了一個(gè)指向字符型變量的指針,未給它賦任何地址之前是不能直接使用它進(jìn)行函數(shù)調(diào)用的,如:gets(p);或strcpy(p,“se”);8.4指針與字符串例8.8將字符數(shù)組a中的字符串拷貝到字符數(shù)組b中(1)下標(biāo)法(2)指針法#include<stdio.h>#include<stdio.h> main()main(){{chara[]=“Hello,world!”,b[20];chara[]=“Hello,world!”,b[20];inti;char*pa,*pb;for(i=0;a[i]!=‘\0’;i++)for(pa=a,pb=b;*pa!=‘\0’;pa++,pb++)b[i]=a[i];*pb=*pa;b[i]=‘\0’;*pb=‘\0’;printf(“%s\n”,b);printf(“%s\n”,b);}}該功能相當(dāng)于:strcpy(b,a);pa=a;pb=b;while(*pa++=*pb++)8.4指針與字符串例8.9將指針變量cp所指向的字符串拷貝到字符數(shù)組ca中(1)下標(biāo)法(2)指針法#include<stdio.h>#include<stdio.h> main()main(){{charca[20],*cp=“Hello,world!”;charca[20],*cp=“Hello,world!”;inti;char*p;for(i=0;cp[i]!=‘\0’;i++)for(p=ca;*cp!=‘\0’;p++,cp++)ca[i]=cp[i];*p=*cp;ca[i]=‘\0’;*p=‘\0’;printf(“%s\n”,ca);printf(“%s\n”,ca);}}該功能相當(dāng)于:strcpy(ca,cp);p=ca;while(*p++=*cp++)注意:循環(huán)結(jié)束后的指針指向,p已指向ca外,未重新賦值前,不能用p輸出ca內(nèi)的串。cp也指向字符串常量外。8.4指針與字符串二、通過指針在函數(shù)間傳遞字符串1、函數(shù)的定義形式例如:charfunc(chara[])
{函數(shù)體;}也可以寫為:charfunc(char*a)
{函數(shù)體;}8.4指針與字符串例8.10設(shè)計(jì)一函數(shù),實(shí)現(xiàn)與標(biāo)準(zhǔn)函數(shù)strcpy類似的功能。
#include<stdio.h>
voidmystrcpy(char*to,char*from);
main()
{charca[20],*cp=“Hello,world!”;
mystrcpy(ca,cp);
printf(“%s”,ca);
}
voidmystrcpy(char*to,char*from)
{
while(*from!=‘\0’){*to=*from;to++;from++;}
*to=‘\0’;
}思考:調(diào)用mystrcpy(ca,cp+2);結(jié)果如何?調(diào)用mystrcpy(ca+2,cp);結(jié)果又如何?while(*from!=‘\0’)*to++=*from++;*to=‘\0’;while(*to++=*from++);8.4指針與字符串例8.21編寫比較兩個(gè)字符串大小的函數(shù),如果兩串相同,返回值為0,否則,返回它們二者第一個(gè)不同字符的ASCII碼差值。
#include<stdio.h>
intmystrcmp(char*,char*);
main()
{charca[50],cp[50];inti;gets(ca);gets(cp);i=mystrcmp(ca,cp);
if(i>0)printf(“%s>%s”,ca,cp);
elseif(i=0)printf(“%s=%s”,ca,cp);
elseprintf(“%s<%s”,ca,cp);
}
intmystrcmp(char*s1,char*s2)
{while(*s1!=‘\0’&&*s2!=‘\0’){if(*s1!=*s2)break;s1++;s2++;}
return(*s1-*s2);}該節(jié)結(jié)束,返回目錄8.5指針與多維數(shù)組數(shù)組是具有相同“數(shù)據(jù)類型”的數(shù)據(jù)的順序集合,而數(shù)組本身也是C語(yǔ)言的一種數(shù)據(jù)類型,同樣可以作為數(shù)組的元素類型。當(dāng)一個(gè)一維數(shù)組的元素類型為數(shù)組時(shí),便構(gòu)成了多維數(shù)組。熟記下面兩組等價(jià)式:
x[i]*(x+i)
&x[i]x+i8.5指針與多維數(shù)組一、通過指針訪問多維數(shù)組1、二維數(shù)組結(jié)構(gòu)的分析設(shè)有數(shù)組定義為:inta[3][4];則有:a表示數(shù)組在內(nèi)存中的首地址,也就是數(shù)組中第1
個(gè)元素(也是第一行)的首地址,它是一個(gè)地址常量,其值由系統(tǒng)在編譯時(shí)確定,程序運(yùn)行期間不能改變。該二維數(shù)組可以理解為:它是一個(gè)一維數(shù)組,含有3個(gè)元素,每個(gè)元素又是一個(gè)一維數(shù)組(該一維數(shù)組含有4個(gè)元素,每個(gè)元素是int類型)。8.5指針與多維數(shù)組二維數(shù)組的邏輯結(jié)構(gòu)圖如下:a[0][0]a[0][1]a[0][2]a[0][3]a[1][0]a[1][1]a[1][2]a[1][3]a[2][0]a[2][1]a[2][2]a[2][3]a[0]a[1]a[2]a+0a+2a+18.5指針與多維數(shù)組2、指向二維數(shù)組中一行的指針變量(或指向一維數(shù)組的指針變量)(1)格式:類型名(*指針變量名)[長(zhǎng)度];(2)例如:int(*pa)[4];(3)含義:pa是指針變量,它指向一個(gè)數(shù)組,數(shù)組
含有4個(gè)元素,每個(gè)元素的類型是int。(4)說明:
a.與定義int*pa;以及int*pa[4];含義不同。b.如果執(zhí)行pa++,則pa實(shí)際增加了多少呢?pa實(shí)際增加了2*4=8個(gè)字節(jié)8.5指針與多維數(shù)組
c.若定義:inta[3][4],(*pa)[4]=a;則關(guān)系圖為:a[0][0]a[0][1]a[0][2]a[0][3]a[1][0]a[1][1]a[1][2]a[1][3]a[2][0]a[2][1]a[2][2]a[2][3]apa(*pa)[0](*pa)[1](*pa)[2](*pa)[3]如果執(zhí)行pa++,則*pa代表a[1],變?yōu)槿鐖D所示papa*pa代表a[0],即第0行,第0行各元素還可以表示為那么(*pa)[0]、(*pa)[1]、(*pa)[2]、(*pa)[3]也變了8.5指針與多維數(shù)組3、幾個(gè)表達(dá)式由x[i]*(x+i)和&x[i]x+i可以得出:
a[i][j](*(a+i))[j]*(a[i]+j)*(*(a+i)+j)&a[i][j]*(a+i)+ja[i]+j8.5指針與多維數(shù)組例8.11用各種方法訪問二維數(shù)組各元素#include<stdio.h>
main()
{
staticintaa[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};
inti,j,*p,(*pa)[4];//第一種方法
for(pa=aa,i=0;i<3;i++){printf(“\n”);
for(j=0;j<4;j++)printf(“%5d”,pa[i][j]);
}8.5指針與多維數(shù)組//第二種方法
for(pa=aa;pa<aa+3;pa++){printf(“\n”);
for(j=0;j<4;j++)printf(“%5d”,(*pa)[j]);
}//第三種方法
for(p=&aa[0][0];p<&aa[0][0]+3*4;p++){if((p-&aa[0][0])%4==0)printf(“\n”);
printf(“%5d”,*p);
}
}8.5指針與多維數(shù)組二、通過指針在函數(shù)間傳遞多維數(shù)組1、函數(shù)的定義形式例如:intfunc(intarray[][4],intn)
{函數(shù)體;}也可以寫為:intfunc(int(*array)[4],intn)
{函數(shù)體;}8.5指針與多維數(shù)組2、函數(shù)的說明形式如有函數(shù)定義:
intfunc(intarray[][4],intn)
{函數(shù)體;}則對(duì)該函數(shù)的說明形式可以寫為:intfunc(intarray[][4],intn);intfunc(int(*array)[4],intn);intfunc(int[][4],int);intfunc(int(*)[4],int);注意:作為形參定義的數(shù)組名是一個(gè)指針變量,它在函數(shù)體中可以變化,這一點(diǎn)與變量定義時(shí)不同。8.5指針與多維數(shù)組例8.12求3行4列二維數(shù)組中的最大元素#include<stdio.h>
intmax_value(int(*pa)[4],introw);
main()
{staticintaa[3][4]={{1,3,5,7},{2,4,6,8},{20,15,32,12}};
printf(“maxelementis%d\n”,max_value(aa,3));
}
intmax_value(int(*pa)[4],introw)
{inti,j,m=pa[0][0];
for(i=0;i<row;i++)
for(j=0;j<4;j++)if(pa[i][j]>m)m=pa[i][j];return(m);
}int(*pb)[4];for(pb=pa;pa<pb+3;pa++)for(j=0;j<4;j++)if((*pa)[j]>m)m=(*pa)[j];8.5指針與多維數(shù)組例8.12求3行4列二維數(shù)組中的最大元素(另一種方法)#include<stdio.h>
intmax_value(int*p,intn);
main()
{staticintaa[3][4]={{1,3,5,7},{2,4,6,8},{20,15,32,12}};
intmax;
max=max_value(&a[0][0],3*4);
printf(“maxelementis%d\n”,max);
}
intmax_value(int*p,intn)
{inti,m=*p;
for(i=0;i<n;i++,p++)
if(*p>m)m=*p;
return(m);
}該節(jié)結(jié)束,返回目錄復(fù)習(xí)2int*p;
指向普通的整型變量或一維數(shù)組的首地址,*p代表一個(gè)整型變量或一維數(shù)組中的某一個(gè)元素。p++的含義?
int(*p)[4];
指向二維數(shù)組一整行,或指向整個(gè)一維數(shù)組,*p代表一整個(gè)一維數(shù)組,其中的每一個(gè)元素用(*p)[i]表示。p++的含義?當(dāng)作為函數(shù)參數(shù)時(shí)都是指針變量,二維數(shù)組的訪問有兩種方法:下標(biāo)法、指針法(一維數(shù)組指針、普通整型指針)。8.6指針數(shù)組與指向指針的指針一、指針數(shù)組1、指針數(shù)組的概念指針數(shù)組是一種特殊的數(shù)組,它每個(gè)元素的類型都是指針類型(即地址),其它與一般數(shù)組相同。2、指針數(shù)組的定義類型名*指針數(shù)組名[常量表達(dá)式];如:int*ap[3];char*s[10];等等。每個(gè)元素ap[i]都等同于一個(gè)普通整型指針變量,可把某個(gè)量的地址賦給該元素(指針變量),該元素即指向那個(gè)變量,即可通過該元素對(duì)相應(yīng)的變量進(jìn)行間接訪問。8.6指針數(shù)組與指向指針的指針3、指針數(shù)組的初始化(1)inta1[5],a2[5],a3[5],*ap[3]={a1,a2,a3};(2)char*sp[]={“abc”,“123”,“Hello”};4、指針數(shù)組的賦值上面的情況中,可以先定義變量,再進(jìn)行賦值,即(1)inta1[5],a2[5],a3[5],*ap[3];
ap[0]=a1;ap[1]=a2;ap[2]=a3;(2)char*sp[3];
sp[0]=“abc”;sp[1]=“123”;sp[2]=“Hello”;例8.13顯示多個(gè)字符串#include<stdio.h>
main()
{
staticchar*ap[3]={“CPU”,“Computer”,“Microprocessor”};
inti;
for(i=0;i<3;i++)puts(ap[i]);
}//以上用指針數(shù)組實(shí)現(xiàn)#include<stdio.h>
main()
{
staticcharaa[3][15]={“CPU”,“Computer”,“Microprocessor”};
inti;
for(i=0;i<3;i++)puts(aa[i]);
}//以上用二維字符數(shù)組實(shí)現(xiàn)8.6指針數(shù)組與指向指針的指針兩種方法中所占內(nèi)存空間的比較CPU\0Computer\0Microprocessor\0ap[0]ap[1]ap[2]aa[0]aa[1]aa[2]apCPU\0Computer\0Microprocessor\08.6指針數(shù)組與指向指針的指針8.6指針數(shù)組與指向指針的指針二、指向指針的指針2、多級(jí)指針的定義類型標(biāo)識(shí)符**指針變量名;
注:*的個(gè)數(shù)代表級(jí)數(shù),要求掌握到二級(jí)即可。如:char**pp,*p,ch=‘A’;又p=&ch;pp=&p;則:1、多級(jí)指針的概念所謂多級(jí)指針,是指指針有多級(jí)指向關(guān)系。&p&ch‘A’pppch8.6指針數(shù)組與指向指針的指針3、多級(jí)指針的含義若定義:char*ps[]={“abc”,“123”,“asd”},**pp=ps;則:*pp為ps[0],即指向“abc”當(dāng)執(zhí)行了pp++后,*pp為ps[1],即指向“123”或*(pp+1)為ps[1],即指向“123”*(pp+2)為ps[2],即指向“asd”二級(jí)指針通常用來訪問字符型的指針數(shù)組,即訪問由指針數(shù)組指向的多個(gè)字符串。例8.14顯示并選擇菜單條目#include<stdio.h>
intgetchoice(char**menu,intn);
main()
{
intchc;
staticchar*mn[5]={“1.Input”,“2.Copy”,
“3.Move”,“4.Delete”,
“5.Exit”};
chc=getchoice(mn,5);
if(chc>=0&&chc<5)printf(“YouchoiceNo.is%s\n”,mn[chc-1]);
elseprintf(“Invalidchoice!\n”);
}8.6指針數(shù)組與指向指針的指針8-14.c傳遞的是指針數(shù)組的首地址,或二維字符數(shù)組的首地址。n代表的是字符串的個(gè)數(shù)。intgetchoice(char**menu,intn)
{
inti,choice;
for(i=0;i<n;i++){puts(*menu);menu++;}printf(\nInputyourchoice:”);
scanf(“%d”,&choice);
return(choice);}8.6指針數(shù)組與指向指針的指針8.6指針數(shù)組與指向指針的指針三、命令行參數(shù)1、命令行參數(shù)的概念1)DOS命令:copyfile1file22)以前的main函數(shù)形式:main()3)帶參main函數(shù):
main(intargc,char**argv);或
main(intargc,char*argv[]);或
main(intargc,charargv[][]);8.6指針數(shù)組與指向指針的指針2、命令行參數(shù)的說明1)形參也可以用其它名字,習(xí)慣上為argc和argv2)argc和argv的值得獲得注:main函數(shù)的調(diào)用由系統(tǒng)完成,所以執(zhí)行程序時(shí)給出的命令行參數(shù)是實(shí)參。如有程序myprog.c,經(jīng)編譯和鏈接生成可執(zhí)行程序myprog.exe,在命令行中輸入:
myprogargument1argument28.6指針數(shù)組與指向指針的指針例:myprogargument1argument2則argc的值為3,argv[0]的值為“myprog”,argv[1]的值為“argument1”,argv[2]的值為“argument2”。3)實(shí)現(xiàn):DOS提示符狀態(tài)下或集成環(huán)境中。例8.15輸出各命令行參數(shù)#include<stdio.h>
main(intargc,char**argv)
{inti;
for(i=1;i<argc;i++)printf(“arg%d:%s\n”,i,argv[i]);
}8.6指針數(shù)組與指向指針的指針該節(jié)結(jié)束,返回目錄執(zhí)行或*(argv+i)若可執(zhí)行文件為myprog,運(yùn)行時(shí)鍵入:myprogComputerandClanguage則輸出為:arg1:Computer
arg2:and
arg3:C
arg4:language8.7返回指針值的函數(shù)1、概念當(dāng)函數(shù)的返回值是指針類型(地址)時(shí),則稱為指針函數(shù)。2、定義類型名*函數(shù)名(形參表);如:int*f(inta);等等。源程序例8.16:編寫函數(shù)
char*mystrchr(char*str,charch);
功能是在str中查找字符ch,返回ch第一次出現(xiàn)的地址,如果找不到,返回空指針NULL。(8_16.c或8_16_2.c)例8.17將一個(gè)字符串轉(zhuǎn)換為大寫形式并輸出#include<stdio.h>
char*mytoupper(char*s);
main()
{charps[80],*s;
gets(ps);s=mytoupper(ps);puts(s);
}
char*mytoupper(char*s)
{
char*t=s;
while(*t!=‘\0’){*t=(*t>=‘a(chǎn)’&&*t<=‘z’)?*t-32:*t;t++;}
return(s);
}8.7返回指針值的函數(shù)該節(jié)結(jié)束,返回目錄動(dòng)態(tài)內(nèi)存分配8.8指向函數(shù)的指針1、函數(shù)名的含義函數(shù)名代表一個(gè)地址,它是函數(shù)的入口,即函數(shù)代碼在內(nèi)存中的起始位置,是一個(gè)指針常量,類似于數(shù)組名。2、概念如果一個(gè)指針指向一個(gè)函數(shù),則稱該指針為函數(shù)指針。(注意與指針函數(shù)的區(qū)別)3、定義
類型名(*指針變量名)(形參表);如:int(*f)(inta,intb);例8.17函數(shù)指針舉例#include<stdio.h>
intmax(inta,intb);
intmin(inta,intb);
main()
{intx=3,y=4,z;
int(*pf)(int,int);
pf=max;z=(*pf)(x,y);printf(maxis%d\n”,z);
pf=min;printf(“minis%d\n,(*pf)(x,y));
}
intmax(inta,intb)
{return(a>b?a:b);}
intmin(inta,intb)
{return(a<b?a:b);}8.8指向函數(shù)的指針該節(jié)結(jié)
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年毫州貨運(yùn)上崗證考試多少道題
- 兒童健康成長(zhǎng)類產(chǎn)品推廣策略匯報(bào)
- 以家庭為單位的教育創(chuàng)新與實(shí)踐探索
- 初四物理教學(xué)計(jì)劃
- 滬教版七年級(jí)第二學(xué)期數(shù)學(xué)期末試題已編
- 企業(yè)員工與孩子健康習(xí)慣培養(yǎng)的異同
- 以信息化提升學(xué)校食品安全的監(jiān)管能力及信息公開透明度
- 全面提高學(xué)生綜合素質(zhì)的實(shí)踐探索
- 創(chuàng)新教育策略在學(xué)生心理健康教育中的應(yīng)用
- 創(chuàng)新教育模式下的創(chuàng)意產(chǎn)業(yè)發(fā)展路徑
- Python數(shù)據(jù)科學(xué)方法與實(shí)踐(山東聯(lián)盟)知到智慧樹章節(jié)測(cè)試課后答案2024年秋山東師范大學(xué)
- 兒童青少年肥胖食養(yǎng)指南(2024年版)
- AI時(shí)代大學(xué)生創(chuàng)新創(chuàng)業(yè)導(dǎo)航智慧樹知到期末考試答案章節(jié)答案2024年西南大學(xué)
- DZ∕T 0336-2020 固體礦產(chǎn)勘查概略研究規(guī)范(正式版)
- 標(biāo)準(zhǔn)節(jié)流裝置計(jì)算
- 三管輪主管設(shè)備的維護(hù)周期(全)解讀
- 鋼結(jié)構(gòu)罩棚施工組織設(shè)計(jì)(共26頁(yè))
- 電力變壓器計(jì)算單
- 清朝年號(hào)干支紀(jì)年對(duì)照表
- 菜么么收銀系統(tǒng)使用說明PPT課件
- 鋼軌超聲波探傷知識(shí)講解
評(píng)論
0/150
提交評(píng)論