語言雜談指針應用詳解_第1頁
語言雜談指針應用詳解_第2頁
語言雜談指針應用詳解_第3頁
語言雜談指針應用詳解_第4頁
語言雜談指針應用詳解_第5頁
已閱讀5頁,還剩12頁未讀 繼續免費閱讀

下載本文檔

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

文檔簡介

C_C++指針指針應用詳前言:復雜類型說要了解指針,多多少少會出現一些比較復雜的類型,類型,要理解復雜類型其實很簡單,一個類型里會出現很多運算符,他們也像普通的表達式一樣,有優先級其優先級和運算優先級一樣,所以我總結了一下其原則:intp;int*p;P處開始,先與*結合,P是一個指針,int結合,說明指針所int型.P是一個返回整型數據的指針intp[3];//P處開始,先與[]結合,P是一個數組,int結合,說明數組里的元素是整型的,P是一個由整型數據組成的數組int*p[3];//P處開始,先與[]結合,因為其優先級比*高,P是一個數組,然后再與*結合,說明數組里的元素是指針類型,int結合,說明指針所指向的內容的類型是整型的,P是一個由指向整型數據的指針所組成的數組.int(*p)[3];P處開始,先與*結合,P//數組,int結合,//整型的.P//組的指針int**p;P開始,先與*結合,P是一個指針,//int結合,//型數據.intp(int);P處起,先與()結合,P是一個函數,//int結合,int*p)(intP處開始,先與指針結合,P是一個指針,//int結合,int型的參數,//int結合,說明函數的返回類型是整型,P返回一個整型數(Anarrayoftenpointerstofunctionsthattakeanintegerargumentandreturnanint*(*p(int))[3];可以先跳過,不看這個類型,//P開始,先與()結合,P是一個函數,//入()里面,int結合,//明數組里的元素是指針,int結合,//針指向的內容是整型數據.P說到這里也就差不多了,我們的任務也就這么多,理解了這幾個類型,其它的類型對我們來說也是小菜了,不過我們一般不會用太復雜的類型,大大減小程序的可讀性,請慎用,這上面的幾種類型已經足夠我們用了.、細說指指針是一個特殊的變量,它里面的數值被解釋成為內存里的一個地址。先幾個指針放著做例子:指針的類從語法的角度看,你只要把指針語句里的指針名字去掉,剩下的(1)int*ptr;//int*(2)char*ptr;//char*(3)int**ptr;//int**指針所指當你通過指針來指針所指向的內存區時,指針所指向的類型決定了從語法上看,你只須把指針語句中的指針名字和名字左邊的指針聲(1)int*ptr;//int(2)char*ptr;//char(3)int**ptr;//int*(4)int(*ptr)[3int()[3](5)int*(*ptr)[4C越來越熟悉時,你會發現,把與指針攪和在一起的"類型"所以看起書來前后,越看越糊涂。指針的 或者叫指針所指向的內存區的地指針的值是指針本身的數值,這個值將被編譯器當作一個地址,32323232位長。指針所指向的內存區就sizeof(指針所指向的類XX為首地址的一片內存區域;我們說一個指針指向了某塊內存區域,指針本身所占據的內324個字節的長度。、charint*ptr=(int*)a;a的類型,ptrptrint*,inta3ptr1,編譯器是這樣ptr1*sizeof(int)32位程序中,是被加上432位程序中,int4個字節。由于地址是用字節做單位的,ptra4個字節。charptra0號單元開始的節,此時指向了數組a中從第4號單元開始的節。intarray[20]={0};int*ptr=array;{ }加1個單元,所以每次循環都能數組的下一個單元。int*ptr=(int*)a;在這個例子中,ptr5ptr的5sizeof(int)3254=20。由于地址ptr5ptr所指向的地址205ptr指向數組a的第0號單元開始的節,加5后,ptr已經指向了數組a的如果上例中,ptr5ptr的5sizeof(int)ptrptr所指向20個字節。intmain(){char*p=a;char}Y誤解:ptrchar的二級指針,ptr++;時,會使指針加一個Y誤解:ptrchar*類型,ptr++;時,會使指針加一個sizeof(char*)(1,那就會得到誤區一的答案,這個值應該是4,參面內容),即&p+4;那進行一次取值運算正解 ptr的類型是char**,指向的類型是一個char*類型,該指向p的地址(&p),ptr++;時,*),即&p+4;那*(&p+4)指向哪呢,這個你去問上帝吧,或者他會告訴你在哪?所以最后的輸出會是一個隨機的值,或許是一個操作.總結一下ptrold加(減)nptrnew,ptrnewptrold的類型相同,ptrnewptrold所指向的類型也相同。ptrnewptrold的值增加(減少)n乘sizeof(ptrold所指向的類型)個字節。就是說,ptrnew所指向的內存ptrold所指向的內存區向高(低)n乘sizeof(ptrold所指向的類型)個字節。兩個指針不能進行加法運算,這是操作,因為進行加法后,得到的、運算符&和&aa的類型加個*a的類型,指針所指向的地址(指針的值)a*p的運算結果就五花八門了。總之*p的結果是ppinta=12;intb;int*p;intp=&a;&aint*//inta*p=24;/*pint//p所指向的地址,顯然,*p就是pa。ptr=&p/&pp的類型加個*,//int**p//int*p*ptr=&b;//*ptr是個指針,&b//的類型和所指向的類型是一樣的,所以用&b來給*ptr**ptr=34;*ptr的結果是ptr//對這個指針再做一次*int、intintarray[10];int*pa;pa=&a/&aInt**ptr=&pa&pa*ptr=&b;//*ptr和&bpa++;這也是指針表達式。charchar**parr=arr;//arr看作指針的話,arrcharstr=*parr;//*parr是指針表達式str=*(parr+1);//*(parr+1)是指針表達式str=*(parr+2);//*(parr+2)在例七中,&a不是一個左值,因為它還沒有占據明確的內存。*ptr是一個左值,因為*ptr這個指針已經占據了內存,其實*ptrpa,pa已經在內存中有了自己的位置,那么*ptr當然也有了自己的位、數組和指針的關intarray[10]={0,1,2,3,4,5,6,7,8,9},value;value=array[0];//也可寫成:value=*array;value=array[3];//也可寫成:value=*(array+3);value=array[4];arrayint[10],但如array0int*,int。因此*array0就一點也不奇怪了。同理,array+33個單元的指針,所以char charstrcpy(s,str[0]);//strcpy(s,*str);strcpy(s,str[1]);//strcpy(s,*(str+1));]);//str是一個三單元的指針數組,該數組的每個單元都是一個指針,str當作一個指針的話,它0char**char**str也是個指針,它的類型是chr*,它所向的類型是ha,它指向的地址是字符串" o,thisiample!"的第個字符的地址,即'的地址注意:字符串相當于是一個數組,在內存中以數組的形式儲存,只不過字符串是一個數組常量,內容不可改變,且只能是右值.如果看成指針的話,他即是常量指針,也是指針常量.str+11char**,char*。下面總結一下數組的數組名(數組中的也是數組)的問題TYPEarray[n]array就有了兩重含義:TYPE[n];第二,它是一個常量0號單元,該指針自己占0號單元占據的內存區是不同的。該array++的表達式是錯誤的。array可以扮演不同的角色(i)在表達式 (等價于sizeof(int[N]))中,數組名array代表數組本身,故這sizeof(i)*array中,array扮演的是指針,因此這個表達式的結果就是0號單元的大小。sizeof(*array)測出的是數組單元的大小。(i)array+n(n=0,1,2,.....)中,arrayn號單元。故sizeof(array+n)324.例十一intarray[10];//array:指向數組首個單元的指針(數組首個單元的地址)或代表數組本身.int(*ptr)[10];//ptr:指向整個數組的指針.ptr=&array&array:整個數組的首地址ptrint(*)[10],他指向的類型是中,array代表數組本身。zof()zeof)測出的是指針自身類型的大小呢還是指針所指向的類型的大小?答案是前者。例如:32位程序中,有:sizeof(對象)、指針和結構類型的可以一個指向結構類型對象的指針。struct{inta;intb;intstructMyStruct//了結構對象ss,并把ss的成員初始化為20,30和40。structMyStruct*ptr=&ss;//了一個指向結構對象ss的指針。它的類型//MyStruct*,MyS*pstr=(int*)&ss;//了一個指向結構對象ss的指針。但是pstr//ptr請問怎樣通過指針ptr來ss的三個成員變量?ptr->a;指向運算符,或者可以這們(*ptr).a,建議使用前者又請問怎樣通過指針pstr來ss的三個成員變量?*pstr;//了ss的成員a*(pstr+1);//了ss的成員b*(pstr+2)//了ss的成員cMSVC++6.0上調式過上述代碼,但是要知道,這樣使用pstr來結構成員是不正規的,為了說明為什么不正規,讓我們看看怎樣通過指針來數組的各個單元:(將結構體換成數組)intarray[3]={35,56,37};int*pa=array;通過指針pa數組array的三個單元的方法是*pa;//了第0號單*(pa+1);//了第1號單*(pa+2);//了第2號單從格式上看倒是與通過指針結構成員的不正規方法的格式一放在連續的區里,單元和單元之間沒有空隙。但在存放結構對象的所以,在例十二中,即使*pstr到了結構對象ss的第一個員變量a,也不能保證*(pstr+1)就一定能到結構成員b。因為成員a和成員b之間可能會有若干填充字節,說不定*(pstr+1)就正好不過指針結構成員的正確方法應該是象例十二中使用指針ptr的、指針和函數的關可以把一個指針成為一個指向函數的指針intfun1(charint(*pfun1)(char*,int);inta=(*pfun1)("abcdefg",7);intfun(char*);inta;charstr[]="abcdefghijklmn";intfun(char{intnum=0;for(inti=0;;){}return}funASCII碼值之strsstrs,s所指向的地址就和str所指向的地址一致,但是str和s各自占用各自的空s1str進行了自1運算。、floatf=12.3;float*fptr=&f;int*p;pfpint*int&ffloat*,floatMSVC++6.0上,對TYEP*TYPE,那么語法格式是:(TYPE*)p;TYPE*TYPE,它指向的地址就是原指針指向的地址。p(切記)voidfun(char*);inta=125,b;voidfun(char*s){}注意這是一個32位程序,故int類型占了節,char類型占一個字節。函數fun的作用是把一個整數的節的順序來個顛倒。注意到了嗎?在函數調用語句中,實參&a的結果是一個指針,它的類型是int*intchar*,它指向的類型是char。這樣,在實參和形參的結合過程中,須進行一int*char*類型的轉換。結合這個例子,我們可以這樣來char*temp,temp=(char*)&atemps。所以最后的結果是:schar*,char,它指向的地址就是a的首地址。3232位整數。那可不可以把一個整數當作指針的值unsignedintTYPE*ptr;//TYPE是int,char或結構類型等等類型。 ;//無符號整數a的值用來表示一個地址. ;//我們的目的是要使指針ptr指向地址ptr=a;//我們的目的是要使指針ptr指向地址unsignedintTYPE*ptr;TYPEint,chara=N//Nptr=(TYPE*)a//嚴格說來這里的(TYPE*)和指針類型轉換中的(TYPE*)還不一樣。這里的(TYPE*)a的值當作一個地址來看待。上面強aptr的時候,就會出現操作錯誤。想想能不能反過來,把指針指向的地址即指針的值當作一個整數intint*ptr=&aptr的值是a的地址,ptra的地址.char*str;b=(int)ptr;//ptrb。str=(char*)b;//char*str。chars='a';int*ptr;ptr=(intptrint*ints32位程序中,s占一個字節,int類型占四ss相臨的序知道,而寫程序的人是不太可能知道的。也許這三個字節里了非指針的馬虎應用,這三個字節的值被改變了!這會造成性的錯誤。charint*ptr=&a;3ptr1運算后,ptra相鄰的高地址方向的一塊區。這塊區里是什么?我們不知道。有可能它是一個非常重要的數據,甚至可能是一條代碼。而第4句竟然往這片區里常清楚:我的指針究竟指向了哪里。在用指針數組的時候,也要注在指針的強制類型轉換:ptr1=(TYPE*)ptr2sizeof(ptr2的類型)大于sizeof(ptr1的類型),那么在使用指針ptr1來ptr2所指向的區時是安全的。如果sizeof(ptr2的類型)小于sizeof(ptr1的類型),那么在使用指針ptr1來ptr2所指向的存儲區時是不安全的。至于為什么,讀者結合例十八來想,應該會明C++是一種靜態類型的語言,C++中舉足輕重.C語言中,void*來指向一切;C++中,void*并不能指向一切,事實上,C++中,想找到一個通用的指針,特別是通用的函數指針簡直是一個"不可能任下面我們來探討一下,C++中如何各種類型數據的指針.數據指針分為兩種:常規這個不用說明了,C語言一樣,定義、賦值是很簡單明了的.常見的有:int*,double*等如intvalue=123;int*pn=structMyStruct{intkey;intvalue;MyStructme;MyStruct*pMe=&me;value成員的地址,我們可以int*pValue&me.value;//int*pValue&pMe- 常規數據指針好了,我們現在需要一種指針,MyStruct中的任一數據成員,子intMyStruct::*pMV&MyStruct::value;//intMyStruct::*pMK這種指針的用途是用于取得結構成員在結構內的地址.我們可以通過該指針來員數據intvaluepMe->*pMV;//取得pMevalue成員數據.intkey=me.*pMK;//me的key成員數據.來的一個函數:intsum(MyStruct*objs,intMyStruct::*pm,int{intresult=for(inti=0;i<count;++i)result+=return}這個函數的功能是什么,你能看明白嗎?它的功能就是,countMyStruct結構的指有點拗口對吧?的程序,你也許就明白了MyStructme[10]{intsum_value=sum(me,&MyStruct::value,//計算10個MyStruct結構的value成員的總和:sum_value值為110 intsum_key=sum(me,&MyStruct::key,10);//計算10個MyStruct結構的key成員的總和:sum_key值為 intsum(MyStruct*objs,intcount){intresult=for(inti=0;i<count;++i)result+=objs[i].value;returnresult;}你是想這么做嗎?但這么做,value,key的話,你要多寫一個函數.有可以相當于隱式的返回值,可以返回的值:#include"iostream.h"voidexample(int*a1,int&b1,int{}void{int*a;intcout<<"*a="<<*a<cout<<"b="<cout}注意到沒有,*ab的值都改變了,c沒有變.a1是指向*a(=6)的指針,a是指向同一個地址所以當a1指向的值改變了,*a的值也就改變了.在函數中的參數使用了(intb的別名,把它當作特殊的指針來理解,b的值會改變.intc1只是在函數中起作便了,所以在main()中不起作用.#include"iostream.h"intint*example1(int{return&a;}int*example2(int{intc=5;return}void{int*a1=example1(10);int*b1=example2(10);cout<<"a1="<<*a1<cout<<"b1="<<*b1<}輸出結果*b14135,15呢由于a是全局變量,存放在全局變量的內存區,它一直是存在的;而局部變量則是存在于函example2()調用結束后便,使b指向了一個不確定的區域,產生指針懸掛.#include"iostream.h"void{char*a1;char*a2;cin>>a1;cincout<<"a1="<cout}輸出Nullpointer#include"iostream.h"void{char*a1;chara1=newchara2=newchar[10];cin>>a1;cincout<<"a1="<cout}C語言所有復雜的指針,都是由各種嵌套構成的.如何解讀復雜指針呢?右左則是一個既著名又常用的方法.不過,C標準里面的內容,C標準的規定中歸納出來的方法.C標準的規則,是用來解決如何創建的,而右左法則是用來解決如何辯識一個的,兩者可以說是相反的.右左法則的英文原文是這樣說的:Theright-leftrule:Startreadingthedeclarationfromtheinnermostparentheses,goright,andthengoleft.Whenyouencounterparentheses,thedirectionshouldbereversed.Onceeverythingintheparentheseshasbeenparsed,jumpoutofit.Continuetillthewholedeclarationhasbeenparsed.右左法則:首先從最里面的圓括號看起,然后往右看,再往左看.每當遇到圓括號時,閱讀方向.一旦解析完圓括號里面所有的東西,就跳出圓括號.重復這個過程直到整個解起,之所以是未定義的標識符,是因為一個里面可能有多個標識符,但未定義的標識符只int(*func)(int*p);func是一個指針,然后跳出這個圓括號,先看右邊,也是一個圓括號,這說明(*func)是一個函數,func是一個指向這類函數的指針,就是一個函數指針,int*類型的形參,返回(*func)(int*p,intfunc被一對括號包含,且左邊有一個*號,func是一個指針,跳出括號,右邊也有個括號,那func是一個指向函數的

溫馨提示

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

最新文檔

評論

0/150

提交評論