c语言数组与指针浅析
? ? ?大部分人,特別是初學者對于一些奇怪的數組表達式表示詫異。
? ? ?舉個例子:
#include<stdio.h> int main(void) { int a[3]; for(int i = 0; i<3; ++i) {*(a+i) = i+1; } //what is this ?! Are you kidding me ?! //---------------------- printf("%d\n",*(a)); printf("%d\n",0[a+1]); printf("%d\n",((*a)[a+1])); return 0; }? ? ?恩,很復雜,很無聊,感覺這樣來表達根本沒有意義。我也承認,把故意把它復雜化了,目的是講清楚一些有關數組與指針的關系。
? ? ?上面的程序,運行結果是把數組元素順序輸出,也就是分別輸出1,2,3。
? ? ?先來看看數組的定義:int a[3];
? ? ?a 是數組名,相信大家都有過數組名 a 作為函數實參的經歷,也就是把數組首元素地址 &a[0] 傳給函數。這說明什么,說明數組名 a 一個指針,默認指向了數組的第一個元素 a[0]。
? ? ?那么 a 作為指針,*a 是什么也就清楚了,*a 可以說是數組第一個元素的引用,也就是說,
*a = a[0]。以此類推 *(a+1) = a[1]……
? ? ?明白這個之后,再來看看下面這個推導“公式”。
? ? ?*a = *(a+0) = a[0] = *(0+a) = 0[a];
? ? ?*(a+1) = a[1] = *(1+a) = 1[a];
? ? ?這些表達式都是對的,a[i] = i[a] 也是成立的。再看看下面的推導:
? ? ?*(a+1+1) = a[2] = *(1+a+1) = 1[a+1];
? ? ?所以,a[2] = 1[a+1] 成立。可以這樣來想,(i)[a+j] = a[i+j];
? ? ?通過以上說明,對c語言數組與指針的關系可能更加清晰了。很多時候,我們會自己另外定義指針來指向數組:
? ? ?通過自己另外定義的指針來對數組進行操作,然而低調的數組名 a ,卻淡然于世外,被人遺忘。
? ? ?所以,回頭看看一開始的那個程序,一切也就明白了,核心就是:數組名就是一個指針,默認指向了數組的首元素。所以,你對數組名的任何指針式的操作都是合法的。
? ? ?上面是一維數組的操作,下面來說說二維數組。
#include<stdio.h> int main(void) { int a[2][2]; a[0][0] = 1; a[0][1] = 2; a[1][0] = 3; a[1][1] = 4; //what is this ?! Are you kidding me ?! //---------------------- printf("%d\n",0[*(a)]); printf("%d\n",*(*(a)+1)); printf("%d\n",3[*(a)-1]); printf("%d\n",1[*(a)+2]); return 0; }? ? 呵呵,這段代碼也挺讓人抓狂的,沒人會這么做,這么做的不是優秀的程序員。我還是那句話,夸張化來說明一些道理。不這么寫,但是一定要明白為什么可以這么寫,這是我的一點追求。
? ? 如果上面一維數組的講解清楚了,那么二維數組其實不難理解。
? ? 先來看看定義:
? ? int a[2][3];
? ? 代表什么意思?可以有很多理解,有些人覺得這可以看成是一個類似坐標的矩陣,比如把第一個[]里面的想成是x軸,第二個[]里面是y軸,所以這樣對a[1][2]就很容易理解,這樣理解是可以的。
? ? 有意思的是,它不過就是一維數組里面有個一維數組而已。拿a[2][3]舉例,也就是說,首先,數組名是 a ,它是一個一維數組a[2],這個一維數組的每一個元素放著什么呢?放著3個元素,把表達式就寫成a[2][3]。跟一維數組一樣,數組名 a 是指針,默認指向a[0][i],但是問題來了,因為a[0][i]當中的內存塊里面有三個int型的分別是a[0][0],a[0][1],a[1][2],究竟指向哪個呢?哪個都不指向,就只是指向a[0][i]而已,那么指向a[0][0]的指針在哪?在這:*a 。 ?*a 就是指向a[0][0]的指針,明白這種關系嗎?這里有個雙重指針。我結合一維數組來解釋一下:
? ? 一維數組中,a 是指針指向首元素,那么有等式【1】 *a = a[0];
? ? 二維數組中,a 是指針指向首元素a[0][i],那么利用上面的等式【1】,a[0][i]可以推導寫出這樣的等式:a[0][i] = *a[i],*a 可以看成是數組名,所以,*a 就是指向 a[0][0] 的指針,這樣就清楚多了,呼~
? ? 所以,理清楚這個關系,輸出**a,也就是輸出a[0][0]了,*(*a+1),當然就是a[0][1]。
? ? 所以,對于三維數組也清楚了吧,***a 就是 a[0][0][0],多維數組以此類推……
? ? 對于這樣的表達式:0[*(a)],也能理解了,推導:(見笑,筆者對邏輯步驟比較感興趣)
? ? 0[*(a)] = *(a)[0] = *a[0] = a[0][0];
? ? 恩,對c語言的數組與指針說得有點復雜,但這些確實很重要,平時編程可以不這么寫,但是一定要懂得里面的原理,這樣的好處不是讓自己能運用,而是讓自己不會運用錯誤。(指針操作錯誤可能引發很大的麻煩)
? ? 水平有限,有些包含不到,有些分析欠佳的,還請諒解。
轉載于:https://blog.51cto.com/listengeek/1346537
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的c语言数组与指针浅析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 跨域调用WebService
- 下一篇: Spring-RestTemplate之