數組的特殊情況
※數組在定義時可以省略下標:
int ai[]={1,2,3};
編譯器會自動算出此數組在初始化時有3個元素,自動定義成int ai[3]={1,2,3};
這種方法經常用在字符串上:
char str[]={“string”};
※二維數組初始化時,只有第一維下標可以省略:
int ai[][3]={{1,2,3},{4,5,6}};
※也可以用一維數組的形式初始化二維數組:
int ai[][3]={1,2,3,4,5,6};
缺胳膊少腿也行:
int ai[][3]={1,2,3,4};
元素ai[1][1]和ai[1][2]會自動初始化為0
※無論多少維數組,它的內存都連成一片,我們可以用通過指針的移動來指向數組中的任何一個元素。
int ai[][3]={1,2,3,4,5,6};
int *pi=&ai[0][0];
pi+=3;
這時pi指向ai[1][0];
注意以下寫法都是錯誤的:
※int ai[][3]={{1,2,3}{4,5,6}};
少了中間的逗號
※int ai[][3]={{1,2,3},{}};
不能用空花括號初始化,一維數組也一樣
※int ai[0];
不能定義只有0個元素的數組
※int ai[3][]={{1,2,3},{4,5,6}};
除第一維下標外,其它維的下標都不能省略
二維數組與指針
在學二維數組與指針之前,我們先回顧下一維數組與指針的關系。
a[3]等價於*(a+3)
a[0]等價於*(a+0)等價於*a
二維數組可當成是“數組的數組”,假設二維數組定義如下:
int a[3][4]={{1,3,5,7},{9,11,13,15},{17,19,21,23}}
a是個數組名,包含3個元素:a[0],a[1],a[2],每個元素又是一個數組,包含4個元素a[0][0],a[0][1],a[0][2],a[0][3]。
從一維數組的知識得知:a[2]相當於*(a+2),但是它只能取到下一維數組的地址,即&a[2][0]。那么如何取到a[1][2]的內容呢?用如下方法:
*(*(a+1)+2)
它等價於
a[1][2]
※一般在沒有&影響的情況下,n維數組中有n個*就會取到數據,小於n個*,只能取到地址。
通過以上表達式,我們可以推出另外幾個表達式:
a[0][1]等價於*(*(a+0)+1)等價於*(*a+1)
a[1][0]等價於*(*(a+1)+0)等價於**(a+1)
a[0][0]等價於*(*(a+0)+0)等價於**(a+0)
題目講解:
已知數組int x[5][4]={0};中x的地址為0x0AFD0100,求**(x+3)+2、*x+3、*(*(x+3)+2)的地址或值。
參考答案:2 0x0AFD010C 0
說明: 一、**(x+3)+2相當於*(*(x+3)+0)+2相當於x[3][0]+2=2
二、*x+3 相當於*(x+0)+3相當於x[0]+3相當於x[0][3]的地址&x[0][3],等於0x0AFD0100+3*4等於0x0AFD0100+C=0x0AFD010C。
三、*(*(x+3)+2)相當於x[3][2]=0
程序1
二維數組與指針的關系

// 31-1二維數組與指針的關系.c #include <stdio.h> main() { int a[2][3] = { 1,3,5,7,9,11 }; //定義二維數組 printf("%d \n", &a); printf("%d,%d \n", a, *a); printf("%d,%d \n", a[0], *(a + 0)); printf("%d,%d \n", &a[0], &a[0][0]); printf("%d,%d \n", a[1], *(a + 1)); printf("%d,%d \n", &a[1], a + 1); printf("%d,%d \n", &a[1][2], *(*(a + 1) + 2)); printf("%d,%d \n", a[1][0], *(*(a + 1) + 0)); }
測試結果:

多維數組
多維數組地址換算

※上圖分析是通過元素個數來是計算地址:例子
求 a[1][2][1] 的地址:
a[1][2][1] = 2116 + (1 * 3 * 2 + 2 *2 + 1) *4 = 2160
※內存是線性結構,數組維數再多,也要通過公式轉換為線性地址將數據存儲在內存中。
