部落格園的我:駿馬金龍: www.cnblogs.com/f-ck-need-u
1.C中陣列和指標的關係
對於任意型別的陣列arr,對於同型別的指標型別parr(確切一點,可以假設型別為int,即int arr[], *parr
)。它們之間有如下"內幕":
1.陣列的名稱arr本身就是一個指標,這個指標指向陣列的第一個元素
2.因為名稱arr本身是指標,所以可以直接賦值給同型別的指標parr:parr = arr
,這使得parr也指向陣列的第一個元素,所以這個賦值過程等價於parr = &arr[0]
3.指標和陣列名在效果上是等價的。它們的區別在於:指標是變數。指標變數可以參與表示式的計算,如parr++
和parr=arr
是有效的,而arr=parr
和arr++
是無效的
4.陣列的各元素在記憶體中是連續的,可以通過索引下標的方式arr[i]
獲取任意一個元素,而arr[i+1]
一定代表下一個元素(除非陣列索引越界),arr[i-1]
一定代表前一個元素(除非沒有前一個元素)
5.因為陣列名也是指標,所以也可以將獲取元素的方式寫成*(arr)
,它等價於arr[0]
,即代表第一個元素的值。同理,*(arr+1)
等價於arr[1]
即表示第二個元素,*(arr+i)
等價於arr[i]
即表示第i+1個元素
6.也就是說,arr
代表第0個元素的地址,arr+1
代表第2個元素的地址,arr+i
代表第i+1個元素的地址
7.也可以直接通過指標的加減法運算取得對應位置的元素地址。parr
代表的是第一個元素(index=0)的地址,parr+1
代表第二個元素(index=1)的地址,parr+i
代表第i+1個元素(index=i)的地址
8.所以,*(parr)
代表的是陣列第一個元素的值,*(parr+1)
代表陣列第二個元素的值,*(parr+i)
代表陣列第i+1個元素的值
9.實際上,陣列索引下標運算就是先轉換成對應的指標,再通過指標去取得對應元素的。所以,使用指標的效率比使用索引下標取陣列值的效率要高,它少了一個轉換過程。或者說,指標和陣列的索引是一一對應的關係
10.由於陣列名指向的是陣列的第一個元素,如果某個指標指向這個陣列中的某個元素,那麼可以說這個指標指向的就是一個子陣列。例如arr是原始陣列,那麼parr+3
是一個子陣列,arr+4
也是一個子陣列。這使得我們可能訪問到陣列第一個元素之前的元素(即父陣列中子陣列之前的元素),比如-1、-2在操作上都是允許的,除非這樣的訪問超越了父陣列的邊界
2.指標和陣列之間的幾個等價概念
等價的方式 | 意義
--------------------------------|---------------------
&arr[i] arr+i parr+i | 都表示index=i元素的地址
--------------------------------|---------------------
arr[i] *(arr+i) *(parr+i) | 都表示index=i元素的值
複製程式碼
特別的,當i=0時:
&arr[0] arr parr 都表示陣列第一個元素的地址
arr[0] *(arr) *(parr) 都表示陣列第一個元素的值
複製程式碼
3.指標運算
指標是變數,可以直接參與表示式的運算,指標是地址,可以進行地址運算。
有效的指標運算包括:
- 相同型別指標之間的相互賦值運算
- 指標與整數之間的加、減法運算。這種運算可以讓指標前移或後移N個陣列的元素
- 指向相同陣列中元素的兩個指標之間的減法或比較運算(指標與指標之間只能進行減法和比較),減法運算得到的結果是指標之間的元素個數(例如
(arr+3) - arr + 1
表示第1個元素到第4個元素之間的4個元素) - 0賦值給指標的運算、0轉換成指標型別的空、指標和0之間的比較
- 其它的運算方式都是非法的
對於指標和整數之間的加減法或指標的自增、自減運算,需要注意的是這些運算子之間的優先順序以及從右向左計算的方式。
parr += 1
表示將指標向後移動一位,等價於++parr
。
*++parr
表示取下一個陣列元素,因為一元運算子*
和++
的優先順序相同,它們從右向左運算。
*parr++
表示取得parr當前指向的元素,但是parr已經指向下一個元素了。
指標之間可以比較大小,當然,只有指向同一陣列的多個指標之間的比較才有意義。p和q兩個指標,如果p指向的元素在q指向的元素之前,那麼p < q
。通過比較指標,也可以很容易判斷陣列的訪問是否越界。例如,判斷指標指向的元素是否在第99個元素之後,對於只有100個元素的陣列來說,這就是在判斷越界。
parr > &arr[99]
parr > arr + 99 // 與上等價
複製程式碼
同理,指向同一陣列的多個指標之間可以進行減法運算(只能進行減法),指標之間的減法運算返回的是這兩個指標之間的元素個數。
4.指標、陣列和函式
C語言是按值拷貝的。
但因為陣列名本身就是指向第一個元素的指標,所以按值拷貝也只是拷貝這個指標,拷貝得到的指標副本仍然指向陣列的第一個元素,並且通過這個指標能夠遍歷到後面的元素。
因為拷貝後得到的副本指標指向的仍然是函式外面的陣列結構,所以在函式內部可以直接通過這個指標修改外部陣列。
下面兩種想要以陣列作為引數的函式在行為上是等價的:
void func1(int arr[]){}
void func1(int *parr){}
複製程式碼
呼叫該函式時,都可以傳遞陣列名或指標給它們:
int arr[];
int *parr;
parr = arr;
func1(arr);
func1(parr);
複製程式碼