1. 指針 1.1 一個指針包含兩方面:a) 地址值;b) 所指向的數據類型。 1.2 解引用操作符(dereference operator)會根據指針當前的地址值,以及所指向的數據類型,訪問一塊連續的記憶體空間(大小由指針所指向的數據類型決定),將這塊空間的內容轉換成相應的數據類型,並返回左值。 ...
1. 指針
1.1 一個指針包含兩方面:a) 地址值;b) 所指向的數據類型。
1.2 解引用操作符(dereference operator)會根據指針當前的地址值,以及所指向的數據類型,訪問一塊連續的記憶體空間(大小由指針所指向的數據類型決定),將這塊空間的內容轉換成相應的數據類型,並返回左值。
有時候,兩個指針的值相同,但數據類型不同,解引用取到的值也是不同的,例如,
1 char str[] ={0, 1, 2, 3}; /* 以字元的ASCII碼初始化 */ 2 3 char * pc = &str[0]; /* pc指向str[0],即0 */ 4 5 int * pi = (int *) pc; /* 指針的“值”是個地址,32位。 */
此時,pc和pi同時指向str[0],但*pc的值為0(即,ASCII碼值為0的字元);而*pi的值為50462976。或許把它寫成十六進位會更容易理解:0x03020100(4個位元組分別為3,2,1,0)。我想你已經明白了,指針pi指向的類型為int,因此在解引用時,需要訪問4個位元組的連續空間,並將其轉換為int返回。
2. 數組
2.1 數組名和指針
通常我們認為數組名是一個指針常量(例如,int a[10]; 那麼a是一個int * const),這種理解是不全面的,正確的理解如下:
作為右值(例如,賦值語句右邊)時數組名可視為指針常量(系統自動轉換);作為左值,例如取地址,sizeof,則不能視為指針。
sizeof(一個數組)返回的是數組大小*每個元素占位元組數;而sizeof(一個指針)返回4。
2.2 二維數組
實際上,不管是一維還是多維數組,都是記憶體中一塊線性連續空間,因此在記憶體級別上,其實都只是一維。
int a[3][4] = {0,1,2,3,4,5,6,7,8,9,10,11}; int ** p; p = (int**)a; /* 不做強制類型轉換會報錯 */
說明:
1)p是一個二級指針,它首先是一個指針,指向一個int*;
2)a是二維數組名,它首先是一個指針,指向一個含有4個元素的int數組;
由此可見,a和p的類型並不相同,如果想將a賦值給p,需要強制類型轉換。
3. 為什麼不能將二維數組名傳遞給二級指針?
假如我們將a賦值給p,p = (int**)a; 既然p是二級指針,那麼當然可以這麼用:**p; 這樣會出什麼問題呢?
1)首先看一下p的值,p指向a[0][0],即p的值為a[0][0]的地址;
2)再看一下*p的值,p所指向的類型是int*,占4位元組,根據前面所講的解引用操作符的過程:從p指向的地址開始,取連續4個位元組的內容。得到的正式a[0][0]的值,即0。
3)再看一下**p的值,誒,報錯了?當然報錯了,因為你訪問了地址為0的空間,而這個空間你是沒有許可權訪問的。
實際上這是某一年華為的面試題。感興趣的還可以把a的類型定義為char類型的二維數組,看看會發生什麼。
4. 二維數組和二級指針相關的參數匹配
5. 那麼問題來了,下題答案是?
6. 關於二維數組,例如a[2][3]
a和a[0]的值一樣,首先a[0]是一個一維數組(數組的數據類型是整數),也是一個指針常量,1:該指針的值是數組第一個元素的地址,2:指向的數據類型是整數。所以a[0]=&a[0][0]。a呢,也是個數組(該數組數據類型是一維數組),a同時也是個指針常量,1:該指針的值等於該數組第一個元素的地址,該數組第一個元素是a[0](a[0]本身也是個一維數組),a[0]的地址是什麼呢,a[0]是個數,該數的數據類型是一個大小為3的整數一維數組。所以a[0]這個數,記憶體大小是12個位元組,數的首地址是xxx。該首地址也即是a[0]這個數組的第一個元素a[0][0]的首地址,(註意:a[0]和a[0][0]也都是數,而且它們的(首)地址相等,區別是他們的數據類型不一樣,a[0]這個數的數據類型是一維數組,a[0][0]這個數的數據類型是整數,數據類型不相等往往大小也不想等,也有時候大小相等),所以a這個指針常量的值a=&a[0][0]。2:a指向的數據類型是一維數組,所以a+1記憶體移動12個位元組(移動一個a所指向的數據類型這麼大)。
數組就是個指針常量,指針常量就是代表一個數組。這是從*(p+n)恆等與p[n]得出這條的。在大多數情況是對的。只在sizeof()和&運算符下,此時不等價。在sizeof()和&(取地址)里,系統把int a[5] 的a不看成指針常量而是看成是一個變數(數),數據類型為一維數組的變數(數)。顯然該變數的大小是20個位元組,且該變數的地址,即&a是a的變數類型(數組)的第一個元素的地址即&a=&a[0]。所以&a也是合法的。現:int a[5],int *const p=a;那麼a和p在大多數情況是等價的,只有在sizeof()和取地址&運算符下不一樣。sizeof(a)=20,sizeof(p)=4。&a=&a[0],&p!=&p[0]。此時a不是一個指針常量而是一個數據類型為一維數組的變數。。。。。這也是由於程式中不保存數組的大小
參考資料:http://blog.csdn.net/wu_nan_nan/article/details/51741030
http://blog.sina.com.cn/s/blog_5c6f793801019t3t.html