標籤:c++ c語言 編程 語言
在上次的教程裡面,我提到了指標。
針對指標,這次我將簡單的講講,後面我還會講到——那個時候你應該有了相當的基礎。
首先,先講講指標類型。
任何類型關鍵字後面加一個*符號,就會變成指標類型。
比如:
char → char* 字元指標
int → int* 整數指標
double→double* 雙精確度指標
甚至還可以這樣:
char*→char** 字元指標的指標類型 →char*** 字元指標的指標的指標類型…
指標本質上是一個記憶體位址值,該記憶體位址上存放的是相互關聯類型的數值。但是void*指標類型例外,它指向的記憶體位址存放的不是void值。
由於現在的記憶體都很大,動不動都是上G。為了說明上面的情況,我假設存在一個16位元組的記憶體如:
圖中每個格子代表一位元組記憶體,可以存放8個bit
依據上節教程說的,1個char變數a,它的尺寸大小是1位元組。可以放在上面的任意一格,這裡我假設放在第一格:
即 假如存在這樣的情況
char a=‘z‘;
a的值‘z‘存放在第一格
然後char* pa = &a;
這裡&運算子表示,取變數a的地址。
那麼pa的值一定就是0
如果變數a在第二格,那麼pa的值就一定是1
這就是說指標是一個地址值,它是由運行時變數的地址決定的。
由於指標也是一個值,所以指標變數也有長度。
在手機和嵌入式環境上,這個地址值通常是4位元組
在PC環境上,這個值會隨系統而變化:
windows: xp上是4位元組 其他系統中,32位程式中是4位元組 64位程式則是8位元組
linux系統:ubuntu 一般是6位元組(實際上是8位元組,只是中間兩個位元組會做加法,最後合成一個6位元組地址,形如:0xffff12345678這樣的地址值)
Mac系統:同linux
在部分單片機,例如51單片機,plc單片機中,這個值甚至只有2位元組,即只有64k記憶體定址範圍
在我上面假設的記憶體環境中,這個值只有半個位元組0x0~0xF
既然指標變數是一個值,所以它也在記憶體中,也有地址。而要記錄這個值,可以用一個指向指標的指標。
繼續上面的假設
char** ppa = &pa;
加入pa的值存放在1的位置
那麼ppa就等於1
即pa=0 ppa=1
當然實際上pa不一定會順序存放在1的位置,也可能在其他位置,視程式實際啟動並執行情況而定。
由於指標記錄的是地址值,所以存在一種特別的指標void*
這種指標記錄的僅僅是地址值,完全不能說明指向的是什麼類型資料的地址。
但是這也有很大的好處,對於那些不關心資料類型的使用者,這個指標就非常有用了。
例如下面的系統函數:
void* memset(void* dest,int val,int count);
該函數的作用是將指定的dest位置的記憶體,填充val,直到填滿count位元組
該函數不關心指定的dest是什麼類型的地址,char的也好,int的也好,double也好,反正我就是往裡面填入val,直到填滿count位元組為止。
所以這種時候,void*指標類型就非常好。
有鑒於此,所有的編譯器都會提供一種預設的方便:即任何類型指標都可以轉換為void*類型,編譯器不會報錯
比如
char* pa = &a;
memset(pa,1,1);
編譯器不會報錯,提示你pa的指標類型不對。而是默默的將其轉換為void*類型。
本節主要初步講解了指標,後面還會繼續慢慢深入講解指標。指標的變化非常多,應用也非常廣。
ps:
編譯器還會默默的進行下列轉換:
char→int
short→int
上述的unsigned版 unsigned char→unsigned int
zerglurker的C語言教程004——指標初步講解