C指針的用法總結(jié)_第1頁
C指針的用法總結(jié)_第2頁
C指針的用法總結(jié)_第3頁
C指針的用法總結(jié)_第4頁
C指針的用法總結(jié)_第5頁
已閱讀5頁,還剩5頁未讀, 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

1、.;C指針的用法總結(jié)char *p, *p, *p;char p,p,p;char *p,*p,*p,*p,*(*p),(*p),(*p); void (*pFun)(int i);大神們看到這些東西腦袋里一定像藍(lán)天白云一樣清晰明了。(1)關(guān)于指針與數(shù)組的存儲a、指針和數(shù)組在內(nèi)存中的存儲形式 數(shù)組pN創(chuàng)建時,對應(yīng)著內(nèi)存中一個數(shù)組空間的分配,其地址和容量在數(shù)組生命周期內(nèi)一般不可改變。數(shù)組名p本身是一個常量,即分配數(shù)組空間的地址值,這個值在編譯時會替換成一個常數(shù),在運行時沒有任何內(nèi)存空間來存儲這個值,它和數(shù)組長度一起存在于代碼中(應(yīng)該是符號表中),在鏈接時已經(jīng)制定好了;而指針*p創(chuàng)建時,對應(yīng)內(nèi)存中

2、這個指針變量的空間分配,至于這個空間內(nèi)填什么值即這個指針變量的值是多少,要看它在程序中被如何初始化,這也決定了指針指向哪一塊內(nèi)存地址。b、指針和數(shù)組的賦值與初始化 根據(jù)上文,一般情況下,數(shù)組的地址不能修改,內(nèi)容可以修改;而指針的內(nèi)容可以修改,指針指向的內(nèi)容也可以修改,但這之前要為指針初始化。如:int p5;p=p+1; 是不允許的而p0=1; 是可以的;/int *p;p=p+1; 是允許的p0=1; 是不允許的,因為指針沒有初始化;/int i; int *p=&i;p0=1; 是允許的; 對于字符指針還有比較特殊的情況。如:char * p=abc;p0=d; 是不允許的 為什么初始化了

3、的字符指針不能改變其指向的內(nèi)容呢?這是因為p指向的是“常量”字符串,字符串a(chǎn)bc實際是存儲在程序的靜態(tài)存儲區(qū)的,因此內(nèi)容不能改變。這里常量字符串的地址確定在先,將指針指向其在后。 而char p=abc;p0=d; 是允許的 這是因為,這個初始化實際上是把常量直接賦值給數(shù)組,即寫到為數(shù)組分配的內(nèi)存空間。這里數(shù)組內(nèi)存分配在先,賦值在后。(2)關(guān)于一些表達(dá)式的含義char *p, *p, *p;char p,p,p;char *p,*p,*p,*p,*(*p),(*p),(*p); 能清晰地知道以上表達(dá)式的含義嗎?(知道的去死?。┑谝唤M:char *p, *p, *p; 分別為char指針;cha

4、r*指針,即指向char*類型數(shù)據(jù)地址的指針;char*指針,即指向char*類型數(shù)據(jù)的指針;他們都是占4字節(jié)空間的指針。如:char c=a;char *p=&c;char *p1=&p;char *p2=&p1; cout*p2endl;第二組:char p,p,p; 分別為一維,二維和三維char型數(shù)組,即數(shù)組,數(shù)組的數(shù)組,的數(shù)組??梢匀缦碌姆绞竭M(jìn)行初始化:char pp3=ab;char pp133=ab;char pp2333=ab; 現(xiàn)在我們嘗試使用第二組三個數(shù)組名對應(yīng)為第一組三個指針賦值,直接賦值的結(jié)果如下:p=pp; /正確p1=pp1; /錯誤p2=pp2; /錯誤 為什么p

5、1和p2的賦值會出錯呢?原因是數(shù)組名為給指針賦值的規(guī)則不是遞歸的,即數(shù)組的數(shù)組可以為數(shù)組的指針賦值,而不可以為指針的指針賦值。這里先了解到這個抽象的規(guī)則,下面講完第三組表達(dá)式,等我們知道數(shù)組的指針和指針的數(shù)組如何書寫后再對這一問題舉例說明。第三組:char *p,*p,*p,*p,*(*p),(*p),(*p); 這一類表達(dá)式的解析方法如下: 首先把整個表達(dá)式分為三部分, 數(shù)據(jù)類型和星號部分+p或括號內(nèi)內(nèi)容部分+中括號部分如:char *(*p)分為char* ,(*p) 和 “char*”表示最內(nèi)層存儲的數(shù)據(jù)類型“(*p)”表示最外層指針“”表示中間層數(shù)組(維數(shù)=中括號數(shù)目),因此上式表示一

6、個一維數(shù)組的指針p,數(shù)組中的元素的數(shù)據(jù)類型是指針char*。同理,char (*p)表示,一個二維數(shù)組的指針的指針,數(shù)組元素的數(shù)據(jù)類型是char。這里如果表達(dá)式中間沒有括號(如*p),則實際上是一個數(shù)組,如果最右沒有中括號(如*p),則實際上是一個指針。下面通過賦值表達(dá)式來理解這些表達(dá)式的含義:char c=a;char *pc=&c;char *p3,*p133,*p23,*p333,*(*p4)3,(*p5)3,(*p6)33,(*(*p7)3;p1=pc;p100=pc;p20=&pc;p300=&pc;(*p4)0=pc;(*p5)0=c;(*p6)00=c;(*p7)0=c; 注意,

7、(*(*p7)3和(*p5)3是等價的。 這里再繼續(xù)上一小節(jié)講一下數(shù)組名給指針賦值的問題。 事實上可以對等賦值的數(shù)組和指針關(guān)系如下(表示“賦值給”):數(shù)組指針 : p*p指針的數(shù)組指針的指針 : *p*p指針的指針的數(shù)組的指針的指針的指針 : *p*p?;驍?shù)組的數(shù)組數(shù)組的指針 : p(*p)數(shù)組的數(shù)組的數(shù)組的數(shù)組的數(shù)組的指針 : p(*p)總之,最外層的數(shù)組可以轉(zhuǎn)換指針,往內(nèi)層不遞歸。(3)關(guān)于上述表達(dá)式的長度 求一個表達(dá)式的“長度”,首先分清表達(dá)式實際表示的是一個數(shù)組還是一個指針;如果是指針,則長度為4byte;如果為數(shù)組則要計算實際存儲的總元素個數(shù)和元素的數(shù)據(jù)類型。另外要注意要求的是數(shù)組元

8、素個數(shù)還是數(shù)組總字節(jié)數(shù);如:*(*p)33 由上文可知上式表示一個指針,因此長度為4byte;而*p333 表示一個二維數(shù)組,數(shù)組元素類型為指針的指針,因此長度為3*3*4=36; 注意,標(biāo)準(zhǔn)C中sizeof函數(shù)求得的是總字節(jié)數(shù)而非數(shù)組長度。(4)關(guān)于函數(shù)的指針返回值和指針參數(shù) 指針作為返回值要注意的地方是不要返回局部數(shù)據(jù)的指針。如:char * fun(void)char i=a;return (&i); 調(diào)用函數(shù)fun得不到值a,原因是函數(shù)返回后,局部數(shù)據(jù)(在棧中)被析構(gòu),數(shù)據(jù)內(nèi)存被回收,指針指向的數(shù)據(jù)沒有意義; 可以改為:char * fun(void)char i=a;char *p=

9、(char *)malloc(5);If(p!=NULL) p0=i, p1=0;return (p); 這里使用malloc分配了內(nèi)存(在堆中)在函數(shù)返回后依然有效。 這里還沒完,因為有一天我使用了下面的代碼:char * fun(void)char *p=abc;return (p);發(fā)現(xiàn)雖然p定義為局部變量,但返回也是正確的。還記得上面講到的常量字符串存儲位置嗎?指針p實際指向了靜態(tài)數(shù)據(jù)區(qū),這里的char *p相當(dāng)于const char *p,這樣的數(shù)據(jù)在函數(shù)返回后是不會被立刻回收掉的。 指針作為參數(shù)主要用于修改指針指向的數(shù)據(jù)內(nèi)容,但修改指針的值無效,如char * fun(char *

10、p)char i=a;p=(char *)malloc(5);p0=i;return p; 因為傳遞的是一個指針副本(形參指針和實參指針的值相同,但不是同一個指針),不會影響調(diào)用方的實參值。(詭異的vs2012貌似可以通過形參將實參的值改掉!不過還是不要冒這個險為好了)。(5)關(guān)于const修飾符 const修飾符用于指針時也非常糾結(jié)。 首先要分清const char *p和char* const p。 const char *p是指向const對象的指針,即對象是只讀的,而指針不是。使用const對象的指針要注意兩點:一是不能將其賦值給非const對象的指針,如:const char* p;

11、char *p1=p; /不允許的 當(dāng)然,直接使用非const指針指向const對象也是不合法的,如:const char c;char *p1=&c;/不允許的, 這是要避免通過上述p1改變const對象的值。 二是可以將非const對象的地址賦值給指向const對象的指針,但是試圖使用這個指針改變變量的值是非法的,如:char c=a; const char* p=&c;/允許的*p=b;/不允許的 char* const p是const指針,即指向?qū)ο罂删庉?,但指針本身不可修改,這一點類似于數(shù)組。如:char c=a; char* const p=&c;*p=b;/允許的p+;/不允許的

12、 區(qū)分兩者的方法是,看const是否靠近指針名,如果是則為const指針,否則為const對象。這個助記方法的前提是char要和*號靠在一起,因為const char* p=char const *p。另外,還有const char* const p,自然是指向const對象的const指針了。(6)關(guān)于指針函數(shù) 首先注意指針函數(shù)和函數(shù)指針的區(qū)別,前者是指“返回指針的函數(shù)”,這在上文中有提到,而后者是指“指向函數(shù)的指針”。 函數(shù)指針的定義方法為,將“函數(shù)名”替換為“(*函數(shù)指針名)”,如: 指向一個聲明為void fun(int a)的函數(shù)指針可以定義為 void (*pFun)(int a)

13、或void (*pFun)(int ),注意這里函數(shù)指針pFun只能指向和fun有相同返回類型(void)和參數(shù)類型(int)的一類函數(shù),另外定義中()也不是擺設(shè),去掉()會被看做是返回值為void*類型的函數(shù)聲明。舉個例子:void fun(int a)coutaendl; int main()void (*pFun)(int);pFun=&fun; /(1)*(pFun)(1); /(2) 事實上,上式中的(1)(2)行做如下幾種替換也是正確的:a、pFun=fun; pFun(1); b、pFun=&fun; pFun(1); c、pFun=fun; *(pFun)(1); 如果有什么疑問的話,可以接著嘗試用如下方式直接調(diào)用函數(shù)fun:(*fun)(1); 運行的結(jié)果也是正確的!這要怎么解釋呢? 其實,fun不僅僅作為函數(shù)名,它同pFun一樣也是一個函數(shù)指針,只不過是函數(shù)指針常量。為了書寫方便,c語言開發(fā)者允許將函數(shù)指針調(diào)用直接寫成類似fun()的形式,同樣函數(shù)指針變量賦值也可以寫成類似pFun=&fun的形式。值得注意的是,函數(shù)聲明的格式還是比較嚴(yán)格的,如:void fun(int ); /不能寫成void (*fun)(int )。 同樣,void (*pFun)(int ); /不能寫成void pFun(int )。 為了方便,我們還可以定義函數(shù)指針類型,

溫馨提示

  • 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)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論