指針可以指向復合類型,上一節講了指向指針的指針,這一節學習指向數組的指針。以下定義一個指向數組的指針,該數組有10個int元素:
int (*a)[10];
和上一節指針數組的定義int *a[10];相比,僅僅多了一個()括號。如何記住和區分這兩種定義呢?我們可以認為[]比*有更高的優先順序,如果a先和*結合則表示a是一個指針,如果a先和[]結合則表示a是一個數組。int *a[10];這個定義可以拆成兩句:
typedef int *t; t a[10];
t代表int *類型,a則是由這種類型的元素組成的數組。int (*a)[10];這個定義也可以拆成兩句:
typedef int t[10]; t *a;
t代表由10個int組成的數組類型,a則是指向這種類型的指針。
現在看指向數組的指針如何使用:
int a[10]; int (*pa)[10] = &a;
a是一個數組,在&a這個表達式中,數組名做左值,取整個數組的首地址賦給指針pa。注意,&a[0]表示數組a的首元素的首地址,而&a表示數組a的首地址,顯然這兩個地址的數值相同,但這兩個表達式的類型是兩種不同的指針類型,前者的類型是int *,而後者的類型是int (*)[10]。*pa就表示pa所指向的數組a,所以取數組的a[0]元素可以用表達式(*pa)[0]。注意到*pa可以寫成pa[0],所以(*pa)[0]這個表達式也可以改寫成pa[0][0],pa就像一個二維數組的名字,它表示什麼含義呢?下面把pa和二維數組放在一起做個分析。
int a[5][10];和int (*pa)[10];之間的關係同樣類似於int a[10];和int *pa;之間的關係:a是由一種元素組成的數組,pa則是指向這種元素的指針。所以,如果pa指向a的首元素:
int a[5][10]; int (*pa)[10] = &a[0];
則pa[0]和a[0]取的是同一個元素,唯一比原來複雜的地方在於這個元素是由10個int組成的數組,而不是基本類型。這樣,我們可以把pa當成二維數組名來使用,pa[1][2]和a[1][2]取的也是同一個元素,而且pa比a用起來更靈活,數組名不支持賦值、自增等運算,而指針可以支持,pa++使pa跳過二維數組的一行(40個位元組),指向a[1]的首地址。