對於指針數組和數組指針,單從字面上似乎很難分清它們是什麼,先來看看指針數組和數組指針各自的定義形式。
指針數組的定義形式為:(是一個數組)
類型名 * 數組名[ 數組長度];
如:
int *p[8];
數組指針的定義形式為:(是一個指針)
類型名 (* 指針名)[ 數組長度];
如:
int (*p)[8];
現在來分析上述兩種定義形式,通過“int *p[8];”這條定義語句可以定義一個指針數組。因為優先級的關系,所以p 先與[] 結合,說明p 是一個數組,然後再與* 結合說明數組p 的元素是指向整型數據的指針。元素分別為p[0], p[1], p[2], ...,p[7],相當於定義了8 個整型指針變量,用於存放地址單元,在此,p 就是數組元素為指針的數組,本質為數組。如果使用的定義方式為“int (*p)[8];”, p 先與* 號結合,形成一個指針,該指針指向的是有8 個整型元素數組,p 即為指向數組首元素地址的指針,其本質為指針。介紹了指針數組和數組指針的含義,接下來,我們通過下面一段代碼來看看指針數組和數組指針如何訪問二維數組。(這裡使用右左法則,通過變量先看右邊,再看左邊)
[cpp] view plaincopy在CODE上查看代碼片派生到我的代碼片
include <stdio.h>
void main(int argc,char *argv[])
{
int arr[4][4]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
int (*p1)[4];
int *p2[4];
int i,j,k;
p1=arr;
printf("使用數組指針的方式訪問二維數組arr\n");
for(i=0;i<4;i++)
{
for(j=0;j<4;j++)
{
printf("arr[%d][%d]=%d\t",i,j,*(*(p1+i)+j));
}
printf("\n");
}
printf("使用指針數組的方式訪問二維數組arr\n");
for(k=0;k<4;k++)
{
p2[k]=arr[k];
}
for(i=0;i<4;i++)
{
for(j=0;j<4;j++)
{
printf("arr[%d][%d]=%d\t",i,j,*(p2[i]+j));
}
printf("\n");
}
return;
}
fengpeng@ubuntu:~/workspace/work1$ ./test
使用數組指針的方式訪問二維數組arr
arr[0][0]=0 arr[0][1]=1 arr[0][2]=2 arr[0][3]=3
arr[1][0]=4 arr[1][1]=5 arr[1][2]=6 arr[1][3]=7
arr[2][0]=8 arr[2][1]=9 arr[2][2]=10 arr[2][3]=11
arr[3][0]=12 arr[3][1]=13 arr[3][2]=14 arr[3][3]=15
使用指針數組的方式訪問二維數組arr
arr[0][0]=0 arr[0][1]=1 arr[0][2]=2 arr[0][3]=3
arr[1][0]=4 arr[1][1]=5 arr[1][2]=6 arr[1][3]=7
arr[2][0]=8 arr[2][1]=9 arr[2][2]=10 arr[2][3]=11
arr[3][0]=12 arr[3][1]=13 arr[3][2]=14 arr[3][3]=15
我們成功地使用數組指針和指針數組的方式訪問了二維數組,在分析它們各自的訪問方式之前,先通過下圖了解二維數組中元素的存放方式。
在分析指針數組和數組指針如何訪問二維數組中的各個元素之前,我們要明白二維數組每行的起始地址並不是只能用圖1-5 中的那種表示方式,還有很多方法可以表示每行的起始地址,如*(arr+i) 和arr+i 等。為了幫助讀者更好地記憶,我們通過下面一段代碼來學習其他表示二維數組每行起始地址的方式。
#include <stdio.h>
void main(int argc,char *argv[])
{
int arr[4][4]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
int i;
for(i=0;i<4;i++)
{
printf("使用arr+i求得二維數組arr第%d行的起始地址為:%d\n",i+1,arr+i);
printf("使用arr[i]求得二維數組arr第%d行的起始地址為:%d\n",i+1,arr[i]);
printf("使用*(arr+i)求得二維數組arr第%d行的起始地址為:%d\n",i+1,(arr+i));
printf("使用&arr[i]求得二維數組arr第%d行的起始地址為:%d\n",i+1,&arr[i]);
printf("\n");
}
return;
}
fengpeng@ubuntu:~/workspace/work1$ ./test
使用arr+i 求得二維數組arr 第1 行的起始地址為:1244996
使用arr[i] 求得二維數組arr 第1 行的起始地址為:1244996
使用*(arr+i) 求得二維數組arr 第1 行的起始地址為:1244996
使用&arr[i] 求得二維數組arr 第1 行的起始地址為:1244996
使用arr+i 求得二維數組arr 第2 行的起始地址為:1245012
使用arr[i] 求得二維數組arr 第2 行的起始地址為:1245012
使用*(arr+i) 求得二維數組arr 第2 行的起始地址為:1245012
使用&arr[i] 求得二維數組arr 第2 行的起始地址為:1245012
使用arr+i 求得二維數組arr 第3 行的起始地址為:1245028
使用arr[i] 求得二維數組arr 第3 行的起始地址為:1245028
使用*(arr+i) 求得二維數組arr 第3 行的起始地址為:1245028
使用&arr[i] 求得二維數組arr 第3 行的起始地址為:1245028
使用arr+i 求得二維數組arr 第4 行的起始地址為:1245044
使用arr[i] 求得二維數組arr 第4 行的起始地址為:1245044
使用*(arr+i) 求得二維數組arr 第4 行的起始地址為:1245044
使用&arr[i] 求得二維數組arr 第4 行的起始地址為:1245044
在上面的代碼中,我們使用了4 種方式來獲得每行的起始地址,因此行起始地址的表示方式並不唯一,讀者在使用的時候可以自行選擇。
下面接著講解數組指針和指針數組是如何訪問二維數組的,先看數組指針的訪問方式。因為數組指針指向的是一個有4 個整型元素的數組,所以可以把二維數組arr 看成由4 個元素arr[0],arr[1], arr[2],arr[3] 組成,每個元素都是含有4 個整型元素的一維數組,所以當在代碼中使用p1=arr 的時候,p1 就指向了二維數組的第一行的首地址。在接下來的訪問中,由於p1 指向的類型是int [4],所以從p1 到p1+1 的變化值為44 個字節,即p1+1=1245012。從前面的運行結果中可以發現,p1+1 剛好指向第二行的起始地址。至於為什麼剛好能指向二維數組arr 的第二行的首地址,這個問題將在第4 章進行講解。通過p1+i 剛好能夠取遍每行的起始地址,有了每行的起始地址之後,就可以通過“*(*(p1+i)+j)”來取出二維數組中每行的每一個元素。指針數組的訪問方式要更容易一些,因為定義的指針數組p2 由4 個元素p2[0],p2[1],p2[2], p2[3] 組成,每個元素都是一個整型指針,所以只需要在程序中取出每行的起始地址並放到p2 指針數組對應的元素中,就可以訪問二維數組arr 中的元素了。所以,在程序中使用指針數組和數組指針的時候,必須對它們有清晰的認識,要知道它們的本質是什麼,以及如何使用。