語言最基礎到指針、文件_第1頁
語言最基礎到指針、文件_第2頁
語言最基礎到指針、文件_第3頁
語言最基礎到指針、文件_第4頁
語言最基礎到指針、文件_第5頁
免費預覽已結束,剩余32頁可下載查看

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領

文檔簡介

C語言與程序設計江漢大學數(shù)學與計算機科學學院韓海指針2有如下的變量定義: charstr[6]; intx=1024,y; floatm;變量的基本屬性10241036104010441048104910501051105210531054myxstr[0]str[1]str[2]str[3]str[4]str[5]變量的屬性:1、變量名2、變量的類型3、變量的值4、變量的地址Q:變量x中存放的1024與內(nèi)存圖右側的地址在含義上有什么不同?31、指稱變量的兩種方法

(1)變量名稱(2)地址存放地址的變量10442、對于如右的內(nèi)存圖,既然內(nèi)存地址表現(xiàn)為非負整數(shù),能否把這樣的數(shù)據(jù)存放在內(nèi)存中?3、變量x與變量y之間存在怎樣的關系?5、x與y中存放的數(shù)據(jù)在功能(類型)上有所不同,如何告訴計算機準備一個能夠存放地址的變量?4、定義:

(1)指針

(2)指針變量(3)指向對象10241036104010441048104910501051105210531054myxstr[0]str[1]str[2]str[3]str[4]str[5]4不帶初值的變量定義形式:

類型 變量名;定義指針變量基類型* 變量名;1、可以寫作“基類型*變量名;”,如:

double*p;

或者 double*p;2、指針變量p占幾個字節(jié)?3、在一行上定義多個指針變量: 基類型*變量1,*變量2,…,*變量n;如:

double*q1,*q2,*q3;4、在一行上混合定義指針變量和普通變量: 基類型*變量1,變量2;如:

double*t1,*t2,x1,x2;5有如下的變量定義: int*p1,*p2,x=1024; doubley;畫出相應的內(nèi)存分配圖定義指針變量與內(nèi)存分配102410001008101210161020yxp2p1Q:1.各變量中能存放什么類型的數(shù)據(jù)2.x的地址能否放進p1中?3.y的地址能否放進p2中?4.x的地址能否再放進p2中?1008p1=&x;1000p2=&y;p2=&x;或者p2=p1;10086定義新類型的格式:

typedef 類型描述新類型名;為指針定義類型1、程序設計者告訴計算機:“下面我用<新類型名>代表<類型描述>”。如:

typedefint

number; typedefunsignedchar

BYTE; typedefint*

pointeri; typedefdouble*

pointerf;2、類型定義寫在程序的什么位置?

(1)main的前面

(2)main的內(nèi)部,變量定義部分3、沒有統(tǒng)一的“指針類型”?;愋筒煌闹羔樥J為具有不同的類型。7用已定義的指針類型定義變量#include<stdio.h>typedefintnumber;typedefunsignedcharBYTE;main(){typedefint*pointeri;typedefdouble*pointerf;

numbern1,n2;BYTEch;pointerip1,p2;pointerfp3,p4;int*p5,x,y;

……}Q:在左邊的程序結構中,有哪些變量的類型相同?第1組,int型:n1,n2,x,y第2組,指針型:p1,p2,p5第3組,指針型:p3,p4注意第2組與第3組是不同的指針類型8建立指向關系有如下的變量定義: int*p1,*p2,*p3,x=1024,y=47;及相應的內(nèi)存分配圖1024100010041008101210161020yxp3p2p1執(zhí)行下面的語句: p1=&x; p2=&y;10041000再執(zhí)行下面的語句: p3=p1; p1=p2;p2=p3;100447100010049畫圖時用箭頭描述指向關系通常,我們并不關心指針值是多少,而關心它指向了誰!1024100010041008101210161020yxp3p2p1100447100010041024100010041008101210161020yxp3p2p11004471000100410指針的同途指針及相關用法主要涉及:1.通過指針間接訪問它所指向的對象2.指針作為系統(tǒng)函數(shù)的入口參數(shù)、計算結果3.用一個指針變量依次指向數(shù)組的各個元素其中又涉及指針的有關計算問題,包括:

(1)如何令指針變量指向數(shù)組的上/下一個元素

(2)判斷兩個指針變量是否指向同一個對象

(3)判斷指針變量是否指向數(shù)組的有效范圍之內(nèi)4.指針作為自定義函數(shù)的參數(shù)或者計算結果前3項在本章講述,第4項在“函數(shù)”一章中穿插講解。11通過指針間接訪問變量1、此處“*”是“間接訪問運算符”。該格式的含義是程序員對計算機說:“我要訪問<地址>處的內(nèi)存單元?!遍g接訪問的格式:

*<地址>2、<地址>的最簡單形式是指針變量。例如有變量定義:

int*p,x,y;解釋下面語句的作用:

p=&x; y=4+(*p); (*p)++;令p指向x以4加上p所指對象的值,結果送y把p所指對象的值加13、語句中使用*p表示“訪問p所指向的對象”,稱為對所指對象的間接訪問。間接訪問的前提是“p有確定的指向對象”。4、p所指向的對象一定是某個內(nèi)存單元,因此可以*p可以放在賦值號的左邊,即: *p=<表達式>;表達式的值應與p的基類型賦值相容。12間接訪問變量示例1指出下面程序中所存在的問題:#include<stdio.h>typedefint*pointer;main(){inta=13,b=35,c;pointert1,t2,t3;t1=&a,t2=&b;printf("a=%d,b=%d,*t1=%d,*t2=%d\n",a,b,*t1,*t2);*t3=*t1,*t1=*t2,*t2=*t3;printf("a=%d,b=%d,*t1=%d,*t2=%d\n",a,b,*t1,*t2);}*t3=*t1錯誤:間接訪問*t3之前,t3必須有確定的指向對象!正確的使用方式見下一頁的示例。13間接訪問變量示例2指出下面程序的運行結果:#include<stdio.h>typedefint*pointer;main(){inta=13,b=35,c;pointert1,t2,t3;

printf("Step1:a=%d,b=%d\n",a,b);t1=&a,t2=&b;

printf("Step2:a=%d,b=%d,*t1=%d,*t2=%d\n",a,b,*t1,*t2);c=*t1,*t1=*t2,*t2=c;

printf("Step3:a=%d,b=%d,*t1=%d,*t2=%d\n",a,b,*t1,*t2);t3=t2,t2=t1,t1=t3;

printf("Step4:a=%d,b=%d,*t1=%d,*t2=%d\n",a,b,*t1,*t2);}Step1:a=13,b=35Step2:a=13,b=35,*t1=13,*t2=35Step3:a=35,b=13,*t1=35,*t2=13Step4:a=35,b=13,*t1=13,*t2=35/*建立指向關系,t1指向a,t2指向b*//*以c為過渡,交換t1和t2所指變量的值*//*以t3為過渡,交換t1與t2的指向關系*/14指針與系統(tǒng)函數(shù)系統(tǒng)函數(shù)(按用途分類):數(shù)學計算類:abs,sqrt,exp,sin,cos等輸入輸出類:printf,scanf,putchar,getchar

字符串處理:strcmp,strlen,strcpy,strcat

其它類:clrscr,randomize,random與系統(tǒng)函數(shù)有關的指針:其中哪些函數(shù)需要以地址作為被處理的數(shù)據(jù)?哪些函數(shù)的處理結果是地址?strcpy,strcatstrcmp,strlen,strcpy,strcat,printf,scanfprintf與scanf關于指針參數(shù)的具體說明見下頁。15指針作為scanf的入口參數(shù)scanf的基本用法:

scanf("格式串",地址1,地址2,……);例如,有如下變量定義和賦值語句:

charfmtstr[]="%d"; intk,*p; p=&k;則下面的語句都可以命令計算機從鍵盤讀入一個整數(shù)送到變量k中:

scanf("%d",&k); ————① scanf("%d",p); ————② scanf(fmtstr,p); ————③常規(guī)用法①是最常見的情況;用法②取變量p中存放的數(shù)據(jù)(即變量k的地址)作為第二參數(shù);用法③的第一參數(shù)(格式串)也采用了指針的形式,是指向數(shù)組元素的指針。實際上,對于用法①,編譯時也是由編譯程序產(chǎn)生一個數(shù)組(數(shù)組名當然由編譯程序安排),再以該數(shù)組的起始地址作為scanf的第一參數(shù)。因此:scanf的各個參數(shù)都是地址;類似地,printf的第一參數(shù)是地址。16指向數(shù)組元素的指針對于如下變量定義:

doublem[10],*p;p的基類型是double,即p的指向對象應是一個能夠存放double型數(shù)據(jù)的內(nèi)存單元;m[0],…,m[9]都是可以存放double型數(shù)據(jù)的內(nèi)存單元,其中的任何一個都可以作為p的指向對象,比如:p=&m[3];C語言規(guī)定:語句中的數(shù)組名代表數(shù)組首元素的地址。即“p=m;”就是“p=&m[0]”。p只能指向數(shù)組m中的某個元素,而不能指向整個數(shù)組。指向數(shù)組的指針見9.5.2節(jié)。需求:數(shù)組m的各個元素在內(nèi)存中依次連續(xù)存放,當p指向m的某個元素時,能否命令計算機:“令p指向m的下一個元素”?17指針表達式(一)計算結果是指針型數(shù)據(jù)的表達式稱為指針表達式,也稱地址表達式。所有需要使用地址的地方都可以寫指針表達式。指針變量是指針表達式的最簡單形式之一,比如:

doublex,y,*q; q=&x; scanf("%lf",q); y=*q+3;指針常量。NULL是程序中可以直接使用的指針常量,NULL可以作為定義各種基類型的指針變量時的初值。比如:

double*t=NULL;此時t不指向任何對象,因而不能用*t訪問t所指對象?!?變量名”和數(shù)組名也被視為指針常量,比如:

ints[8],z,*p1=s,*p2=&s[7],*p3=&z;18指針表達式(二)這是一種特殊的計算,參與計算的數(shù)據(jù)具有不同的類型。<指針>必須有基類型,記存放一個基類型的數(shù)據(jù)需要K字節(jié),即K=sizeof(基類型)。上述計算按如下方式進行:

<指針>±<整數(shù)>*K把<指針>值作為非負整數(shù),按無符號整數(shù)運算規(guī)則計算。計算結果是無符號整數(shù)(非負整數(shù)),是指針類型。示例: ints[4],*p=s; floatt[3],*q=&t[1]; p+=3; q++;處理細節(jié)見下頁。<指針>±<整數(shù)>19指針表達式(三) ints[4],*p=s; floatt[3],*q=&t[1]; p+=3; q++;設各變量從內(nèi)存地址1000處依次連續(xù)安排,內(nèi)存圖如右圖。p+=3即p=p+3,計算過程

p+3 →1000+3*2 →10061000100010021004100610081010101410181022s[0]s[1]s[2]s[3]pt[0]t[1]t[2]q10141006類似地,q+1的計算如下:

q+1 →1014+1*4 →1018101820指針表達式(四)關于指針的強制轉換設 int*t;

double*s;賦值語句“t=s;”能否執(zhí)行?有些編譯程序會給出警告或者錯誤提示:賦值不相容。另一些編譯程序認可該賦值。如果確實要使t和s存放同一個地址值,可以使用強制類型轉換,寫作“t=(int*)s;”。注意:分別用*t和*s間接訪問所指對象會得到不同的結果。建議初學者不要把基類型不同的指針變量相互賦值。21指針表達式(五)以void為基類型的指針

void*q;q是指針變量,其中可以存放一個內(nèi)存地址即使q的值不是NULL,也不能用*q間接訪問q所指對象q通常用作臨時存放某個地址供后續(xù)使用應用示例:設q是如上定義的指針變量,當前指向一片連續(xù)的內(nèi)存區(qū)域,如何把一個整數(shù)放到該段內(nèi)存的最前面兩個字節(jié)?存在的困難:不能直接以類似“*q=5;”的形式處理,因為系統(tǒng)并不知道q所指向的是一個整型存儲單元。解決方法:定義一個基類型是整型的指針變量r,令其指向q所指的同一個位置,再以*r的形式訪問該段內(nèi)存。 int*r; r=(int*)q; *r=5;22間接訪問運算符前面曾經(jīng)介紹過間接訪問的基本形式為:*<地址>確切的形式應為:*(<地址表達式>)即先計算出<地址表達式>的值,然后訪問該值所對應的內(nèi)存單元。比如,對于變量定義:

doubledata[10];解釋下面賦值語句的具體過程:

data[0]=14; *(data+1)=*data+1;注意*(data+1)與*data+1的不同。23<指針1>-<指針2>與指針間的比較前面曾經(jīng)介紹過:<指針>±<整數(shù)>其計算結果是指針類型的數(shù)據(jù)。相應地有:<指針1>-<指針2>兩個指針必須具有相同的類型記共同的基類型對應的字節(jié)數(shù)是K,則按下面方式用整數(shù)規(guī)則計算:

(<指針1>-<指針2>)÷K其計算結果是整數(shù),可以是正數(shù)、負數(shù)、0。代表兩個指針所指向的對象在內(nèi)存安排上相隔多遠。比較兩個指針是否相等,即判斷是否指向同一個對象。比較兩個指針的大小,用于判斷所指對象在內(nèi)存中的位置前后關系。24用指針掃描一維數(shù)組(一)前面曾經(jīng)介紹過:<指針>±<整數(shù)>可以通過計算使一個指針變量指向數(shù)組中的其它元素應用示例:比較下面三段程序的異同。程序段中出現(xiàn)的各個變量定義為:inti,data[10],*p;A段: for(i=0;i<10;i++) printf("%d\n",data[i]);B段: for(i=0;i<10;i++) printf("%d\n",*(data+i));C段: for(q=data;q<=&data[9];q++) printf("%d\n",*q);訪問內(nèi)存的方式不同。C段的方法執(zhí)行時間稍短。25用指針掃描一維數(shù)組(二)#include<stdio.h>#include<stdlib.h>#defineN10main(){intbuf[N],i,*m,*n,*q;randomize();for(i=0;i<N;i++)buf[i]=random(100);if(buf[1]>buf[0])m=buf,n=m+1;elsen=buf,m=n+1;for(q=buf+2;q<buf+N;q++)if(*q<*m)n=m,m=q;elseif(*q<*n)n=q;printf("\n\ndata1=%ddata2=%d\n",*m,*n);}分析該程序的功能,指出各指針變量的作用。產(chǎn)生N個100以內(nèi)的隨機數(shù)初始化m和n如果找到一個比m所指對象還小的如果找到一個比n所指對象還小的產(chǎn)生數(shù)據(jù)處理數(shù)據(jù)輸出26用指針掃描二維數(shù)組二維數(shù)組定義與內(nèi)存分配設有如下的變量定義:

intnum[6][4];從1000處開始安排,畫出內(nèi)存圖。10001002100410061008……1014……1040104210441046num[0][0]num[0][1]num[0][2]num[0][3]num[1][0]……num[1][3]……num[5][0]num[5][1]num[5][2]num[5][3]用指向整型的指針變量依次取值1000、1002、……1046,可以逐個地指向數(shù)組的各個元素。

int*q; q=&num[0][0]; for(i=0;i<4*6;i++) {訪問q所指元素; q++; }27指針數(shù)組的概念顧名思義,指針數(shù)組是能夠存放若干個基類型相同的指針的存儲單元。若有類型定義: typedefint*pointer;則如下定義的數(shù)組就是指針數(shù)組:

pointerp[10];等價于:

int*p[10];或者: int*p[10];不能寫作:

int(*p)[10]; 這是二級指針

(int*)p[10]; 這是強制轉換28定義一組指針變量對于下面的變量定義和語句序列,假設各變量從內(nèi)存2000開始依次安排,試在內(nèi)存圖上說明計算機的執(zhí)行過程。typedefint*pointer;pointerp[5];intdata[5],i;for(i=0;i<5;i++) *(data+i)=i*i;for(i=0;i<5;i++) p[4-i]=data+i;014916效果:一組指針變量指向各自的對象。200020042008201220162020202420282032203620402044idata[0]data[1]data[2]data[3]data[4]p[0]p[1]p[2]p[3]p[4]29利用指針數(shù)組進行排序在不改變原始數(shù)據(jù)的條件下,利用指針數(shù)組可以記載各數(shù)據(jù)的大小關系,從而達到排序的效果。p[0]p[1]p[2]p[3]p[4]data[0]data[1]data[2]data[3]data[4]2435131927建立初始的指向關系完成排序之后p[0]p[1]p[2]p[3]p[4]data[0]data[1]data[2]data[3]data[4]2435131927p[0]p[1]p[2]p[3]p[4]data[0]data[1]data[2]data[3]data[4]2435131927第1次外循環(huán)做完之后30二級指針之一—指向指針變量的指針如果把存放基本類型數(shù)據(jù)的變量稱為普通變量,則普通變量的地址稱為一級指針,用于存放一級指針的變量是一級指針變量。例如:

intx=-9124,*p=&x;-91241000100410081012px1008一級指針變量自身的地址稱為二級指針,用于存放二級指針的變量是二級指針變量。例如,又有變量q存放了p的地址,則q是二級指針變量。1004定義二級指針變量q的方法之一是:

int**q;建立q指向p的指向關系仍然是:

q=&p;q31二級指針與指向對象若q是二級指針變量,則通過q可以間接訪問其指向的一級指針變量,也可以間接訪問一級指針的指向對象。設 intx=-94,y=27,*p,**q; p=&x,q=&p;則 *q相當于p,**q相當于x。例如,依次執(zhí)行下面的語句: *q=&y; -----(1) **q=x; -----(2) (**q)--; -----(3) (*q)--; -----(4)-9410001004100810121016qpyx2710041012-94-95理論上說,可以定義三級指針、四級指針……,并相應地有多級間接訪問,但沒有實用價值。1008101232二級指針之二—指向數(shù)組的指針右邊是二維數(shù)組的內(nèi)存分布圖:

intnum[4][3];對二維數(shù)組的理解:4行3列共12個元素,每個元素可以存放一個int型數(shù)據(jù)。1000100210041006100810101012101410161018102010221024num[0][0]num[0][1]num[0][2]num[1][0]num[1][1]num[1][2]num[2][0]num[2][1]num[2][2]num[3][0]num[3][1]num[3][2]10001006101210181024num[0]num[1]num[2]num[3]另一種理解:每一行是由3個元素構成的一維數(shù)組;如果以這樣的“行”作為基本元素,num可看作是由4個行構成的一維數(shù)組。num的4個元素分別是num[0]、num[1]、num[2]、num[3],num代表首元素num[0]的地址(即指向num[0]的指針),而num[0]又是數(shù)組,因此num就是指向數(shù)組的指針。這是二級指針的另一種形式。num以及num[0]、num[1]、num[2]、num[3]都是數(shù)組名,而C語言規(guī)定語句中使用數(shù)組名就是相應數(shù)組首元素的地址。因此有各種等價寫法(見下頁)。33關于數(shù)組的各種寫法對于二維數(shù)組num和整型變量i、j:

intnum[4][3],i,j;num[i][j]:第i行、j列元素num[i][j]能夠存放一個int型數(shù)據(jù),相當于一個int型變量,可以放在賦值號的左側。num[i]:第i行是由3個元素構成的數(shù)組,num[i]相當于一維數(shù)組名,是指向num[i][0]的指針(一級指針),num[i]等價于&num[i][0],是地址數(shù)據(jù),不能放在賦值號的左側。指針num[i]的基類型是int。num:num是二維數(shù)組名,是指向num[0]的指針(二級指針),相當于&num[0],是地址數(shù)據(jù),不能放在賦值號的左側。指針num的基類型是由3個元素構成的數(shù)組。num[i][j]:num[i]:num:34二維數(shù)組的各種等價寫法num[i][j]:相當于一個int型變量,等價于*(num[i]+j)當j為0時,num[i][0]等價于*num[i]由于num[i]等價于*(num+i),因此num[i][j]又等價于*(*(num+i)+j)num[i]:是指向num[i][0]的一級指針,等價于&num[i][0],也等價于*(num+i)當i為0時,num[0]等價于&num

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論