以前一直有種誤解:
二維數組的是數組的數組,所以數組的首地址是指向第一個元素指標,而這個元素又是一個數組,所以把數組首地址理解為指向指標的指標。
如int a[3][2];,以前一直認為a是一個指向int指標的指標,即是一個int**。最近發現這是錯的。
如果int **p=a; 編譯就會報錯。如果強制轉換int **p=(int **)a,則使用p[i][j]訪問數組元素時出錯。
首先,因為a的定義為 int a[3][2];則a的類型是int* [3][2]數群組類型,或者int* [][2],即指向大小為2的數組的指標,類型與int **不同,所以int **p=a;出錯。
其次,考慮p[i][j]訪問a的數組元素時出錯的問題。當我們使用指向二維數組的指標的下標運算來訪問數組元素時,如a[i][j],它等同於*(a+i*2+j);即必須要知道第二維的大小才能訪問。考慮我使用p[i][j]的後果:p是int**,所以p[i]為*(p+i),而這個結果被視作一個指標,在這裡記做pp=*(p+i),所以p[i][j]等同於pp[j]。最終的結果為*(pp+j),並將這個結果解釋為一個int值。
例如:
int a[3][2];<br />int val=0;</p><p>for(int i=0;i<3;++i)<br />{<br />for(int j=0;j<2;++j)<br />{<br />a[i][j]=val++;<br />}<br />}</p><p>/*使用a[i][j]的方式顯然可以正常訪問該二維數組*/<br />/*下面使用指標直接存取,當然是不是int**了……*/<br />int *p=&a[0][0];/*注意,此處使用int *p=a;或者int *p=a[0];是不對的,p的類型是int型指標,*a或者a[0]是int (*)[2]類型,編譯會報錯的,*<br />*儘管&a[0][0]、a、a[0]的數值相同……*/<br />for(int i=0;i<6;++i)<br />{<br />p[i];/*這樣可以遍曆所有元素*/<br />}</p><p>/*下面看看int**型的指標吧……*/<br />int **pA=(int **)a;/*a、pA類型不同,不強制轉換編譯會報錯*/</p><p>/*下面運行時出錯……*/<br />for(int i=0;i<3;++i)<br />{<br />for(int j=0;j<2;++j)<br />{<br />p[i][j];<br />}<br />}
上面最後一部分pA[i][j]出錯的原因如下:
如上所述:p[i]是*(p+i),即在p處移動i個類型單位大小(p的類型是int**,通常指標都是32位值吧……多數情況正好和int大小相同),所以正好移動i個int大小,假設i=0,j=1,則p[i]是0;那麼p[i][j]就是0[1],相當於將地址4的值取出來解釋為為int ,地址4當然不允許使用者程式訪問,所以執行階段錯誤……