有關指針類型的一點討論
指針是C語言的重要組成部分,也是它迷人之所在。在C語言裏,指針同變量一樣也是有類型的,比如int MyInt語句聲明了一個整型的變量MyInt,int * MyPoint語句聲明了一個指向整型數據的指針,等等,於是乎就引出了指針類型轉換的問題。
原則上來説數據放在内存中無所謂什麽類型,都是以二進制方式存放的,你解釋成什麽就是什麽,但是有個長度問題。比如有個指針指向内存0処,也就是内存地址0這個字節処,那麽如何確定這個指針所指數據段的長度呢?因爲指針只標明了數據的起始地址(本例中是0),到那兒結束它沒說,那就好了,有可能是就在00処結束——此指針所指的數據佔1個字節,也有可能結束在内存地址9処,共佔10個字節,亦有可能結尾在0xFFFFFFFF処,那拍我的内存沒這麽多,你都可以這樣想象。事實上void類型的指針就是這種類型,它就沒有標定結尾。這種“莫名其妙”的東西是C++引入的新特性,以後你就知道它很有用了。
爲了解決所指數據長度之問題,就有了數據類型的概念。數據類型規定每种確定類型的數據有一定的長度,比如int型的數據佔2個字節,long類型的佔4個字節,char類型的佔1個字節等等(這個跟具體的機器有關,但大多數機器都如此),void類型的(又回來了)不確定佔多少個字節。這樣一來便好了,還是上面那個例子,我聲明個指向int類型數據的指針MyPoint並初始化它讓其指向内存地址0処, 它就知道它指的東西是内存地址0至3処共4個字節的數據,因爲我們將MyPoint聲明成int型指針,int類型佔4個字節。
如上代碼寫成:
int * MyPoint;
MyPoint = 0x0;
由此我們得出結論:所謂的數據類型僅是告訴編譯器數據塊兒在内存中的長度,比如從某一個地址到另一個地址這裡系列連續的内存單元都是某一變量的範圍。那void呢?void是如此奇怪它有頭無尾無法確定“管轄範圍”,故而void類型的指針有一些限制,它不能做運算。
指針的運算
指針是可以運算的,沒錯兒,指針運算非常有意思,我就經常這樣算。
什麽運算得到什麽,整數運算得到整數,字符運算得到……,,,字符那個就不能運算了
,所以指針運算得到的還是指針。
一個地址0你讓它向後偏移3個字節就得到了地址3(0+3=3),這就是指針的運算。指針的運算不能“想當然”,要“格外小心”。指針所指的目標地址是個字節單元之地址,但是其運算的單位度量未必就是字節了,要眎具體情況而定。指針運算這樣規定:對某一類型的指針加減(指針運算只能加減)是該類型所佔字節數整數倍字節量之偏移。舉例就明白了:比如老子聲明了一個int型的指針MyPoint,它指向内存地址0処,那麽MyPoint + 1 = 内存地址2,爲什麽呢?因爲int類型佔4個字節,+1表示向後偏移一個單位,這個“單位”就是int型,也就是2個字節,那麽0+2=2。同理如果MyPoint指向的是long型,那麽+1的結果就是4。不僅如此我還要告訴你什麽類型的指針算出來還是該類型的指針,比如剛才的int型指針的例子算出來的新指針起始地址為2,它還是int型的指針,故它的結束地址是3。指針運算就是這樣“以己度人”。
由此可以看出void型的指針不能運算,因它他自己都不知道自己指的是什麽數據類型,也就不知道自己指的東西有多長,也就“無己”了,自然無法“度人”。
指針的(強制)轉換
有了類型就難免不遇到轉換的問題。有時候我們生命一個指針,當時也不知道它要指什麽類型的東西,於是把它聲明為void類型,當我們“清白了”就地把它轉換成某种確定類型的指針,比如int型的。現面有個粒子用來説明這個問題:
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include <stdio.h>
void main(void)
{
int MyInt = 100;
void * p_v;
int * p_i;
p_i = &MyInt;
p_v = (int *)&MyInt; //①
printf("*p_v = %d/n",*p_v); //②
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
代碼首先聲明了int型的變量MyInt並賦值。然後聲明了一個void類型的指針p_v和int型的指針p_i。接下來分別讓其指向變量MyInt,代碼①処由於p_v指針是void類型的所以做強制轉換成int型指針,於是後面的就同int指針沒區別了。
注意,在指針轉換中有人喜歡寫出類似“p_v = (int *)p_i;”這樣的代碼,這是錯誤的,儘管編譯器不會報錯但事實上並沒有做真正的轉換。
其實①処的代碼寫成“p_v = &MyInt;”也可以,不過相應②処的代碼的改成“printf("*p_v = %d/n",*((int *)p_v));”,因爲我們不知道void型指針所知的東西有多長,所以不能確定要打印多少。
在VC中,如果指針的類型不同一定要明確的強制轉換,否則編譯器彙報錯。
末了順便說一下,在32位機中,任何類型的指針(哪怕void型的)都是佔4個字節(也就是32位)這是不變的,轉換了類型它自身也還是4個字節,我們今天討論的都是指指針指向的内容,它指的什麽事可以變的,這兩個概念不要混淆了。
C语言指针解析
8283

被折叠的 条评论
为什么被折叠?



