2017年 1月 15日 指针 学习整理
有關(guān)指針的概念:
指針是一個(gè)特殊的變量,它里面存儲(chǔ)的數(shù)值被解釋為內(nèi)存里的一個(gè)地址。
FIrst of all:我們需要明確目標(biāo)
關(guān)于指針的學(xué)習(xí)以及使用我們需要搞清楚有關(guān)指針的四個(gè)內(nèi)容:指針的類型,指針?biāo)赶虻念愋?#xff0c;指針的值(或者說(shuō)叫指針?biāo)赶虻膬?nèi)存區(qū)),還有指針本身所占用的內(nèi)存區(qū)(指針也是一個(gè)特殊的變量嗎,它肯定也是占據(jù)內(nèi)存的)。接下來(lái)讓我們分別進(jìn)行學(xué)習(xí)。
我們先來(lái)申明幾個(gè)指針的例子:
1 int *ptr; 2 char *ptr; 3 int **ptr; 4 int (*ptr)[3]; 5 int *(*ptr)[4];The First:指針的類型
從語(yǔ)法的角度來(lái)看,你將指針聲明的語(yǔ)句(如:int *ptr;)中的指針名去掉就是指針本身的類型。(指針的類型分很多種)
?
int *ptr; //指針類型是int * char *ptr; //指針類型是char * int **ptr; //指針類型是int ** int (*ptr)[3];// 指針類型是int(*)[3] int *(*ptr)[4];// 指針類型是int *(*)[4]?
還可以吧!這部分應(yīng)該是很好理解的。
?
The Second:指針?biāo)赶虻念愋?/span>
?當(dāng)你通過(guò)指針來(lái)訪問(wèn)指針?biāo)赶虻膬?nèi)存區(qū)時(shí),指針?biāo)赶虻念愋蜎Q定了編譯器將把那片內(nèi)存區(qū)里的內(nèi)容當(dāng)做什么來(lái)看待。
從語(yǔ)法上看,你只須把指針聲明語(yǔ)句中的指針名字和名字左邊的指針聲明符*去掉,剩下的就是指針?biāo)赶虻念愋汀@?#xff1a;
?
int *ptr; //指針?biāo)赶虻念愋褪莍nt char *ptr; //指針?biāo)赶虻牡念愋褪莄har int **ptr; //指針?biāo)赶虻牡念愋褪?int * int (*ptr)[3]; //指針?biāo)赶虻牡念愋褪?int()[3] int *(*ptr)[4]; //指針?biāo)赶虻牡念愋褪?int *()[4]?
在指針的算術(shù)運(yùn)算中,指針?biāo)赶虻念愋陀泻艽蟮淖饔谩??
指針的類型(即指針本身的類型)和指針?biāo)赶虻念愋褪峭耆煌瑑蓚€(gè)概念。當(dāng)你對(duì)C越來(lái)越熟悉時(shí),你會(huì)發(fā)現(xiàn),把與指針攪和在一起的“類型”這個(gè)概念分成“指針的類型”和“指針?biāo)赶虻念愋汀眱蓚€(gè)概念,是精通指針的關(guān)鍵點(diǎn)之一。我看了不少書(shū),發(fā)現(xiàn)有些寫(xiě)得差的書(shū)中,就把指針的這兩個(gè)概念攪在一起了,所以看起書(shū)來(lái)前后矛盾,越看越糊涂(想學(xué)好指針還是好好看我的博客吧-_-)。
?
The Third:指針的值
?指針的值是指針本身存儲(chǔ)的數(shù)值,這個(gè)值將被編譯器當(dāng)作一個(gè)地址,而不是一個(gè)一般的數(shù)值。在32位程序里,所有類型的指針的值都是一個(gè)32位整數(shù),因?yàn)?2位程序里內(nèi)存地址全都是32位長(zhǎng)。?
指針?biāo)赶虻膬?nèi)存區(qū)就是從指針的值所代表的那個(gè)內(nèi)存地址開(kāi)始,長(zhǎng)度為sizeof(指針?biāo)赶虻念愋?的一片內(nèi)存區(qū)。以后,我們說(shuō)一個(gè)指針的值是XX,就相當(dāng)于說(shuō)該指針指向了以XX為首地址的一片內(nèi)存區(qū)域;我們說(shuō)一個(gè)指針指向了某塊內(nèi)存區(qū)域,就相當(dāng)于說(shuō)該指針的值是這塊內(nèi)存區(qū)域的首地址。?
指針?biāo)赶虻膬?nèi)存區(qū)和指針?biāo)赶虻念愋褪莾蓚€(gè)完全不同的概念。在例一中,指針?biāo)赶虻念愋鸵呀?jīng)有了,但由于指針還未初始化,所以它所指向的內(nèi)存區(qū)是不存在的,或者說(shuō)是無(wú)意義的。?
以后,每遇到一個(gè)指針,都應(yīng)該問(wèn)問(wèn):這個(gè)指針的類型是什么?指針指向的類型是什么?該指針指向了哪里? (尤其是在初學(xué)階段,剛開(kāi)始學(xué)習(xí)費(fèi)點(diǎn)時(shí)間沒(méi)關(guān)系,不然日后.....)
The Fourth:指針本身所占據(jù)的內(nèi)存區(qū)
?指針本身到底占據(jù)了多大內(nèi)存呢?你只需要用sizeof(指針的類型)函數(shù)測(cè)一下就可以知道了。在32位的機(jī)器里,指針本身占據(jù)4個(gè)字節(jié)的長(zhǎng)度。
64位機(jī)器應(yīng)該是8個(gè)字節(jié)(具體忘了,有用64位機(jī)子的自己測(cè)一下,Re我。。)
指針本身占據(jù)的內(nèi)存這個(gè)概念在判斷一個(gè)指針表達(dá)式是否是左值(后面講到,此處暫可忽略)時(shí)很有用。
?
好,到這里指針?biāo)拇髼l已經(jīng)講完了,是不是感覺(jué)很簡(jiǎn)單呢!
?
指針的算數(shù)運(yùn)算:
我們剛才已經(jīng)知道指針其實(shí)是一個(gè)特殊的變量,所以它是可以的進(jìn)行運(yùn)算的。指針的運(yùn)算和通常的算術(shù)運(yùn)算不太相同。
eg:
char a[20]; int *ptr=a; ... ... ptr++;我們定義了char數(shù)組a,指針ptr初始化為整形變量a,這時(shí)指針指向char數(shù)組a的內(nèi)存開(kāi)始的地方,也就是指向了a[0],然后ptr++,然而它不是+1這么簡(jiǎn)單。我們假設(shè)ptr指針指向的類型是T,那么ptr++就等同于ptr+=sizeof(T)。在上面的例子中由于char所占一個(gè)字節(jié),ptr恰好+1,此時(shí)他指向了a[1]。若T是int類型,ptr++==ptr+sizeof(int){sizeof(int)==4},同樣它由指向a[0]指向了a[1];
char a[20]; int *ptr = a; ... ... ptr += 5;在這個(gè)例子中,ptr被加上了5,編譯器是這樣處理的:將指針ptr的值加上5乘sizeof(int),在32位程序中就是加上了5乘4=20。由于地址的單位是字節(jié),故現(xiàn)在的ptr所指向的地址比起加5后的ptr所指向的地址來(lái)說(shuō),向高地址方向移動(dòng)了20個(gè)字節(jié)。在這個(gè)例子中,沒(méi)加5前的ptr指向數(shù)組a的第0號(hào)單元開(kāi)始的四個(gè)字節(jié),加5后,ptr已經(jīng)指向了數(shù)組a的合法范圍之外了(此時(shí)ptr指向啥玩意沒(méi)人知道,也許是別的程序的內(nèi)存,也許是空內(nèi)存,還有可能系統(tǒng)不允許訪問(wèn))。雖然這種情況在應(yīng)用上會(huì)出問(wèn)題,但在語(yǔ)法上卻是可以的。這也體現(xiàn)出了指針的靈活性。?
如果上例中,ptr是被減去5,那么處理過(guò)程大同小異,只不過(guò)ptr的值是被減去5乘sizeof(int),新的ptr指向的地址將比原來(lái)的ptr所指向的地址向低地址方向移動(dòng)了20個(gè)字節(jié)。?
總結(jié)一下,一個(gè)指針ptrold加上一個(gè)整數(shù)n后,結(jié)果是一個(gè)新的指針ptrnew,ptrnew的類型和ptrold的類型相同,ptrnew所指向的類型和ptrold所指向的類型也相同。ptrnew的值將比ptrold的值增加了n乘sizeof(ptrold所指向的類型)個(gè)字節(jié)。就是說(shuō),ptrnew所指向的內(nèi)存區(qū)將比ptrold所指向的內(nèi)存區(qū)向高地址方向移動(dòng)了n乘sizeof(ptrold所指向的類型)個(gè)字節(jié)。一個(gè)指針ptrold減去一個(gè)整數(shù)n后,結(jié)果是一個(gè)新的指針ptrnew,ptrnew的類型和ptrold的類型相同,ptrnew所指向的類型和ptrold所指向的類型也相同。ptrnew的值將比ptrold的值減少了n乘sizeof(ptrold所指向的類型)個(gè)字節(jié),就是說(shuō),ptrnew所指向的內(nèi)存區(qū)將比ptrold所指向的內(nèi)存區(qū)向低地址方向移動(dòng)了n乘sizeof(ptrold所指向的類型)個(gè)字節(jié)。
?
?
運(yùn)算符&和*
?
這里&是取地址運(yùn)算符,*是...書(shū)上叫做“間接運(yùn)算符”。&a的運(yùn)算結(jié)果是一個(gè)指針,指針的類型是a的類型加個(gè)*,指針?biāo)赶虻念愋褪莂的類型,指針?biāo)赶虻牡刂仿?#xff0c;那就是a的地址。*p的運(yùn)算結(jié)果就五花八門(mén)了。總之*p的結(jié)果是p所指向的東西,這個(gè)東西有這些特點(diǎn):它的類型是p指向的類型,它所占用的地址是p所指向的地址。
eg:
1 int a=12; 2 int b; 3 int *p; 4 int **ptr; 5 p=&a;//&a的結(jié)果是一個(gè)指針,類型是int*,指向的類型是int,指向的地址是a的地址。 6 *p=24;//*p的結(jié)果,在這里它的類型是int,它所占用的地址是p所指向的地址,顯然,*p就是變量a,即a被賦值成了24。 7 ptr=&p;//&p的結(jié)果是個(gè)指針,該指針的類型是p的類型加個(gè)*,在這里是int**。該指針?biāo)赶虻念愋褪莗的類型(int*)。該指針?biāo)赶虻牡刂肪褪侵羔榩自己的地址(循環(huán)相指,好好想想昂)。 8 *ptr=&b;//*ptr是個(gè)指針,&b的結(jié)果也是個(gè)指針,且這兩個(gè)指針的類型和所指向的類型是一樣的,所以?amp;b來(lái)給*ptr賦值就是毫無(wú)問(wèn)題的了。 9 **ptr=34;//*ptr的結(jié)果是ptr所指向的東西,在這里是一個(gè)指針,對(duì)這個(gè)指針再做一次*運(yùn)算,結(jié)果就是一個(gè)int類型的變量。自己最好多寫(xiě)幾個(gè)小程序練習(xí)一下,練幾次就明白了。
?
指針表達(dá)式:
?一個(gè)表達(dá)式的最后結(jié)果如果是一個(gè)指針,那么這個(gè)表達(dá)式就叫指針表達(dá)式。下面是一些指針表達(dá)式的例子: ?
?
1 int a,b; 2 int array[10]; 3 int *pa; 4 pa=&a;//&a是一個(gè)指針表達(dá)式。 5 int **ptr=&pa;//&pa也是一個(gè)指針表達(dá)式。 6 *ptr=&b;//*ptr和&b都是指針表達(dá)式。 7 pa=array; 8 pa++;//這也是指針表達(dá)式。?
1 char *arr[20]; 2 char **parr=arr;//如果把a(bǔ)rr看作指針的話,arr也是指針表達(dá)式 3 char *str; 4 str=*parr;//*parr是指針表達(dá)式 5 str=*(parr+1);//*(parr+1)是指針表達(dá)式 6 str=*(parr+2);//*(parr+2)是指針表達(dá)式由于指針表達(dá)式的結(jié)果是一個(gè)指針,所以指針表達(dá)式也具有指針?biāo)哂械乃膫€(gè)要素:指針的類型,指針?biāo)赶虻念愋?#xff0c;指針指向的內(nèi)存區(qū),指針自身占據(jù)的內(nèi)存。
好了,當(dāng)一個(gè)指針表達(dá)式的結(jié)果指針已經(jīng)明確地具有了指針自身占據(jù)的內(nèi)存的話,這個(gè)指針表達(dá)式就是一個(gè)左值,否則就不是一個(gè)左值。 在例七中,&a不是一個(gè)左值,因?yàn)樗€沒(méi)有占據(jù)明確的內(nèi)存。*ptr是一個(gè)左值,因?yàn)?ptr這個(gè)指針已經(jīng)占據(jù)了內(nèi)存,其實(shí)*ptr就是指針pa,既然pa已經(jīng)在內(nèi)存中有了自己的位置,那么*ptr當(dāng)然也有了自己的位置。
數(shù)組和指針的關(guān)系:
eg:
?
1 int array[10]={0,1,2,3,4,5,6,7,8,9},value; 2 ... 3 ... 4 value=array[0];//也可寫(xiě)成:value=*array; 5 value=array[3];//也可寫(xiě)成:value=*(array+3); 6 value=array[4];//也可寫(xiě)成:value=*(array+4);上例中,一般而言數(shù)組名array代表數(shù)組本身,類型是int [10],但如果把a(bǔ)rray看做指針的話,它指向數(shù)組的第0個(gè)元素,類型是int *,所指向的類型是數(shù)組單元的類型即int。因此*array等于0就一點(diǎn)也不奇怪了。同理,array+3是一個(gè)指向數(shù)組第3個(gè)單元的指針,所以*(array+3)等于3。其它依此類推。?
?
?
?
?
指針和結(jié)構(gòu)類型的關(guān)系:
可以用于聲明一個(gè)指向結(jié)構(gòu)類型對(duì)象的指針。
eg:
?
1 struct MyStruct 2 { 3 int a; 4 int b; 5 int c; 6 } 7 8 MyStruct ss={20,30,40};//聲明了結(jié)構(gòu)對(duì)象ss,并把ss的三個(gè)成員初始化為20,30和40。 9 MyStruct *ptr=&ss;//聲明了一個(gè)指向結(jié)構(gòu)對(duì)象ss的指針。它的類型是 10 MyStruct*,它指向的類型是MyStruct。 11 int *pstr=(int*)&ss;//聲明了一個(gè)指向結(jié)構(gòu)對(duì)象ss的指針。但是它的類型和它指向的類型和ptr是不同的。?
請(qǐng)問(wèn)怎樣通過(guò)指針ptr來(lái)訪問(wèn)ss的三個(gè)成員變量? ?
ptr->a; ptr->b; ptr->c;指針和函數(shù)的關(guān)系:
可以把一個(gè)指針聲明成為一個(gè)指向函數(shù)的指針。
?
int fun1(char*,int); int (*pfun1)(char*,int); pfun1=fun1; .... .... int a=(*pfun1)("abcdefg",7);//通過(guò)函數(shù)指針調(diào)用函數(shù)。?
可以把指針作為函數(shù)的形參。在函數(shù)調(diào)用語(yǔ)句中,可以用指針表達(dá)式來(lái)作為實(shí)參。 ?
指針到此宣告結(jié)束
?
?
?
?
?
?
?
?
轉(zhuǎn)載于:https://www.cnblogs.com/suishiguang/p/6287806.html
總結(jié)
以上是生活随笔為你收集整理的2017年 1月 15日 指针 学习整理的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: installshield学习笔记
- 下一篇: 前后端分离实践一