博客園的我:駿馬金龍: www.cnblogs.com/f-ck-need-u數組
對於任意類型的數組arr,對於同類型的指針類型parr(確切一點,能夠假設類型爲int,即int arr[], *parr
)。它們之間有以下"內幕":bash
1.數組的名稱arr自己就是一個指針,這個指針指向數組的第一個元素函數
2.由於名稱arr自己是指針,因此能夠直接賦值給同類型的指針parr:parr = arr
,這使得parr也指向數組的第一個元素,因此這個賦值過程等價於parr = &arr[0]
spa
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個元素的值3d
9.實際上,數組索引下標運算就是先轉換成對應的指針,再經過指針去取得對應元素的。因此,使用指針的效率比使用索引下標取數組值的效率要高,它少了一個轉換過程。或者說,指針和數組的索引是一一對應的關係
10.因爲數組名指向的是數組的第一個元素,若是某個指針指向這個數組中的某個元素,那麼能夠說這個指針指向的就是一個子數組。例如arr是原始數組,那麼parr+3
是一個子數組,arr+4
也是一個子數組。這使得咱們可能訪問到數組第一個元素以前的元素(即父數組中子數組以前的元素),好比-一、-2在操做上都是容許的,除非這樣的訪問超越了父數組的邊界指針
等價的方式 | 意義
--------------------------------|---------------------
&arr[i] arr+i parr+i | 都表示index=i元素的地址
--------------------------------|---------------------
arr[i] *(arr+i) *(parr+i) | 都表示index=i元素的值
複製代碼
特別的,當i=0時:code
&arr[0] arr parr 都表示數組第一個元素的地址
arr[0] *(arr) *(parr) 都表示數組第一個元素的值
複製代碼
指針是變量,能夠直接參與表達式的運算,指針是地址,能夠進行地址運算。cdn
有效的指針運算包括:blog
(arr+3) - arr + 1
表示第1個元素到第4個元素之間的4個元素)對於指針和整數之間的加減法或指針的自增、自減運算,須要注意的是這些運算符之間的優先級以及從右向左計算的方式。索引
parr += 1
表示將指針向後移動一位,等價於++parr
。
*++parr
表示取下一個數組元素,由於一元運算符*
和++
的優先級相同,它們從右向左運算。
*parr++
表示取得parr當前指向的元素,可是parr已經指向下一個元素了。
指針之間能夠比較大小,固然,只有指向同一數組的多個指針之間的比較纔有意義。p和q兩個指針,若是p指向的元素在q指向的元素以前,那麼p < q
。經過比較指針,也能夠很容易判斷數組的訪問是否越界。例如,判斷指針指向的元素是否在第99個元素以後,對於只有100個元素的數組來講,這就是在判斷越界。
parr > &arr[99]
parr > arr + 99 // 與上等價
複製代碼
同理,指向同一數組的多個指針之間能夠進行減法運算(只能進行減法),指針之間的減法運算返回的是這兩個指針之間的元素個數。
C語言是按值拷貝的。
但由於數組名自己就是指向第一個元素的指針,因此按值拷貝也只是拷貝這個指針,拷貝獲得的指針副本仍然指向數組的第一個元素,而且經過這個指針可以遍歷到後面的元素。
由於拷貝後獲得的副本指針指向的仍然是函數外面的數組結構,因此在函數內部能夠直接經過這個指針修改外部數組。
下面兩種想要以數組做爲參數的函數在行爲上是等價的:
void func1(int arr[]){}
void func1(int *parr){}
複製代碼
調用該函數時,均可以傳遞數組名或指針給它們:
int arr[];
int *parr;
parr = arr;
func1(arr);
func1(parr);
複製代碼