天天看點

指針變量與數組的關系及什麼是指針數組

指針變量與數組的關系及什麼是指針數組:

  • 一維數組:

數組原本就是以指針的格式使用的,數組名a相當于char * const a。但這裡需要注意的是數組名表示的是一個數組的首位址,是一個位址常量,不能給位址常量指派,但能改變該位址所指向的内容,比如之前a首位址存放的内容為1,可以使用

*a=2

改變該位址單元裡的内容。

在輸出數組元素的值時一般以a[0]形式輸出,該a[0]形式相當于*

*a、*(a+0)

char a[1],*p;

引用一維數組a的第i個元素,有下标法和指針法。假設指針變量p指向數組的首元素(p=a),則有四種數組元素的表示方法:

a[i] ↔ p[i] ↔ *(p(是變量)+i) ↔ *(a(是常量)+i)

a相當于c語言的宏替換#define a 位址常量。p是一個變量,是要把改變量所存放的位址常量取出來參加運算。

這裡需要注意的是,指針變量和數組在通路數組中的元素時,一定條件下其使用方法具有相同的形式,因為指針變量和數組名都是位址量。但指針變量和數組的指針(或叫數組名)在本質上是不同的,數組在記憶體中的位置在程式運作過程中是無法動态改變的。是以,數組名是位址常量,指針是位址變量。數組名可以在運算中作為指針參與,但不允許被指派。

  • 二維數組:

二維數組實際上是以一維數組的方式連續存放的,比如這裡定義一個二維數組int c[2][2],可以把這二維數組當作是由兩個一維數組組成的,然後我們在以一維數組的通路方式去通路數組元素,第一行的一維數組名為c[0],第二行的一維數組名為c[1]。這兩個一維數組名與首數組名c類型一樣,都是位址常量。首數組名c等于第一行一維數組名c[0], c+1就等于第二行的一維數組名c[1]。是以去通路二維數組也和一維數組一樣。

這裡定義一個指針int p=c[0]。

第一行:

c[0][i] ↔ *(p+i) ↔ *(c[0]+i) ↔ *(*(c+0)+i) ↔ *(&c[0][0]+i)

第二行:

c[1][i] ↔ *(c[1]+i) ↔ *(*(c+1)+i) ↔ *(&c[1][0]+i)

這裡需要注意的是,(c+1)的結果是第二行的首位址,不是該位址所指向的内容。也就是*(c+1)等價于c[1](前提是二維數組。在一維數組中*(a+1)傳回的是位址所指向的内容,不是位址),這裡實際也說明了數組本身就是以指針的形式去處理的。

指針數組:顧名思義,就是由同種類型的指針變量構成的數組。

比如有如下定義:

char p[2];

這裡需要注意的是,由于“[ ]”的優先級高于“”,是以,數組名p先于“[ ]”結合,構成一個數組形式,然後該數組在與“*”結合,構成指針數組形式。

這裡說下指針數組名與非指針數組名的差別(一維數組舉例):

非指針一維數組名的是位址常量,是一級指針形式。而指針的一維數組名也是一個位址常量,但該位址是二級指針形式。

之前我們知道了以為數組值可以用下标法引用,但也可以用指針法引用,比如:

a[1]等價于*(a+1)

是以引用指針數組元素可以使用:((p+i)),也就是**(p+i),或者*p[i]來引用。

指針數組首位址是二級指針位址常量,是以可以定義一個二級指針變量來指向該二級指針位址常量,即 char p1=p;或者也可以用p1=&p[0]來指向,這兩種形式是一樣的。

下面講下如何使用指針數組來周遊非指針二維數組中的元素:

這裡先定義一個字元二維數組:char c[2][2]={1,2,3,4};

然後再定義一個指針數組,将指針數組指向該字元二維數組:char *p[2]={ c[0] , c[1] };

那麼,如何通路字元二維數組的第一行元素呢?

我們知道p[0]儲存的是c[0]位址常量或者說儲存的是&c[0][0],是以p[0]指向第一行第一列的内容,即值1。那麼如何指向第一行第二列的值呢,很簡單下,先用p[0]取出第一行第一列的位址,然後将位址加一,即p[0]+i,在将該位址的值取出,即(p[0]+i),然後我們知道p[0]也可以表示成*(p+0),是以又可以表示成*((p+0)+i),同理,第二行數組元素的值可以表示成(*(p+1)+i)。

繼續閱讀