道不盡的“指針”和“數組”

1. 一個基本的數據類型(包括結構體等自定義類型)加上“*”就構成了一個指針類型的
模子。這個模子的大小是一定的,與“*”前面的數據類型無關,“*”前面的數據類型
只是說明指針所指向的內存中存數的數據類型。所以在32位系統下,不管是什麼樣的指針
類型,其大小都是4byte,void *也不例外。

2. 以指針的形式訪問和以下標的形式訪問:
例如:
char *p = "abcdef";
定義了一個指針變量p,p本身佔四個字節,p裏存儲的是一塊內存的首地址。
我們如果需要讀取字符'e'有兩種方式:
a. 以指針形式:*(p + 4),先取出p裏存儲的地址值,假設爲0x0000FF00,然後加上
4個字符的偏移量,得到新的地址0x0000FF04。然後取出0x0000FF04地址上的值。
b. 以下標的形式:p[4],p[4]這個操作被解析成:先取出p裏存儲的地址值,然後加上
中括號中4個元素的偏移量,計算出新的地址,然後從新的地址中取出值。
也就是說:以下標的形式訪問在本質上與以指針的形式訪問沒有本質區別,只是寫法上不同罷了。

char a[] = "123456";
定義了一個數組a,a擁有7個char類型的元素,其空間大小爲7。
a.以指針形式:*(a + 4),a這個時候代表的是數組元素的首地址,假設爲0x0000FF00,
然後加上4個字符的偏移量,得到新的地址0x0000FF04,然後再取出0x0000FF04地址上的值。
b. 以下標的形式:a[4],a[4]這個操作會被解析成:a作爲數組首元素的首地址,然後加上中括號中
4個元素的偏移量,計算出新的地址,然後從新的地址中取出值。
需要說明的是,以上的偏移量的單位是元素的個數而不是byte數。
通過上面的例子,我們似乎感覺數組和指針說的是一回事,但是,我們要記住:
數組就是數組,指針就是指針,他們是完全不同的兩碼事,他們之間沒有任何關係,只是
經常穿着相似的衣服來迷惑你罷了。

3. 一個問題:
int a[5] = {1,2,3,4,5};
int *ptr = (int *)(&a + 1);
這個時候ptr指向哪個數?
對指針進行加1操作,得到的是下一個元素的地址,而不是在原有地址值上直接加1。
所以,一個類型爲T的指針的移動,以sizeof(T)爲移動單位。
&a + 1:取數組a的首地址,該地址的值加上sizeof(a)的值,即&a + 5*sizeof(int),
也就是下一個數組的首地址,顯然當前指針已經超過了數組的界限。

假如把a和ptr的地址,還有*ptr打印出來(16進制):

31fa44
31fa58
-858993460

我們發現58-44=14,轉化成10進制正好是20(5*4,5個int)。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章