1. 程式人生 > >C語言陣列與指標學習總結

C語言陣列與指標學習總結

     工作之後最害怕的是對最基礎知識的考查,因此還是有必要隨時回爐學習,溫故知新。今天再次回顧總結一下C語言陣列相關知識。主要是學習《C語言陷阱與缺陷》的學習筆記。

       C語言陣列值得注意的有兩點:

       1,C語言中只有一維陣列,而且陣列的大小必須在編譯時期就確定下來(舊標準)。然而,C語言陣列的元素可以是任意物件,包括陣列。這樣就給多維陣列的實現或者模擬提供了可能。

       2,對於陣列,我們只能夠做兩件事。一是獲取陣列的大小,二是獲得指向陣列下標為0的元素的指標。其他的任何操作雖說看起來像是陣列,但是本質上其實都是基於指標的操作。

       以上兩天總結摘取自《C語言陷阱與缺陷》,讓我想起了之前自己看過的國外的一份C語言資料結構與演算法的講義。其中關於C語言陣列與指標的知識給了一個重點關注點的概括——除了作為sizeof的引數以外,其它時候C語言陣列的名稱跟指向陣列首元素的指標是等價的。

       關於C語言中陣列的運算機制如何實現是關係到對陣列理解的一個重點。其實,這就是要學會(或者說是記住)C語言陣列宣告定義的形式以及含義。

       1,int a[3];

              定義了一個元素個數為3個的陣列a,其中每個元素都是int型別。

       2, struct

{

       int p[4];

       double x;

}b[17];

定義了一個元素個數為17個的陣列b,其中每個元素都是一個結構體。

       3,int a[12][31];

              宣告定義了一個數組a,該陣列有12個元素,其中每個元素是一個擁有31個元素的陣列,每個最小子元素的型別都是int。這個地方理解時候一定不能夠按照前面兩個例子的順序,從左到右一個個數字字元進行解析。需要記住的還是最前面的那一點,C語言中只有一維陣列,而陣列名稱後面跟著的第一個數字維度就是陣列的真實維度。除此之外,其他的引數則是陣列元素的資訊描述。

       陣列名稱與指向陣列的指標的等價之處在兩種表示的等價,如果定義了一個數組a,那麼陣列的下表為i的元素可以表述為:

       *(a + i) 或者a[i]

       實際上,後者只是前者的一種常用的簡寫方式。

       而由於上面這種描述,其實a[i]和i[a]表示的含義一樣。編寫如下測試程式碼;

#include"stdio.h"

int a[5] ={1,2,3,4,5,};

int main(void)

{

       printf("%d\n",a[3]);

       printf("%d\n",3[a]);

       return 0;

}

       其中,陣列定義的時候我故意在最後的元素後面加上了一個逗號。其實,這並不是錯誤。本來我也不是很理解這種方式,在對了《UNIX程式設計藝術》一書之後才明白。其實,這算是C語言設計的一個優秀的特點,這種特徵不僅方便陣列元素的擴充時候的修改,而且方便陣列的工具生成。程式的編譯以及執行記錄如下;

E:\WorkSpace\01_程式語言\01_C語言\01_C語言陷阱與缺陷\exp02>gccexp02.c

E:\WorkSpace\01_程式語言\01_C語言\01_C語言陷阱與缺陷\exp02>a

4

4

       由上面的驗證可以得出先前陳述的結論或者推論。

       接下來通過簡單的程式碼,回顧二維陣列與指標的關係基礎知識。編寫程式碼如下:

E:\WorkSpace\01_程式語言\01_C語言\01_C語言陷阱與缺陷\exp02>gccexp02.c

#include"stdio.h"

int a[12][31];

int *p;

int i;

int main(void)

{

       p = a[4];

       printf("value of p: %p\n",p);

       printf("size of a[4]:%d\n",sizeof(a[4]));

       a[4][7] = 3;

       i = a[4][7];

       printf("value of i: %d\n",i);

       i = *(a[4] + 7);

       printf("value of i: %d\n",i);

       i = *(*(a + 4) + 7);

       printf("value of i: %d\n",i);

       return 0;

}

       編譯後,執行結果如下:

E:\WorkSpace\01_程式語言\01_C語言\01_C語言陷阱與缺陷\exp02>a

value of p:00405630

size of a[4]: 124

value of i: 3

value of i: 3

value of i: 3

       其中,a[4]的含義自然是代表陣列a的下標為4的元素,而元素的為31個int型別物件。通過計算其佔用的空間可以看出這一點。而進一步來看,其實a[4]應該是一個31個元素的陣列的陣列名。這樣,a[4]也就等同於這個陣列的首地址。在程式中,我通過指標賦值的方式輸出了這個地址數值。接下來的元素取值就值得去品味一下了:

       第一次i取值:使用了陣列名後面加中括號指明偏移來實現;

       第二次i取值:進一步把第一步中的方式改成了指標取值的方式,通過首地址加偏移的方式。

       第三次i取值:把迭代著的一個數組進一步展開。從最終的形式上看,這種方式比使用下標取值的簡寫方式要難理解不少。

       最終i的三次輸出都是相同的,其實這也算是對三種方式等價的一個最基本的驗證。而把a賦值給p是錯誤的,因為a的含義是一個指向“二維陣列的指標”。在程式碼中加入相應的程式碼測試的時候,gcc編譯器會給出警告。不過,程式還是能夠編譯通過並執行。