工作之後最害怕的是對最基礎知識的考查,是以還是有必要随時回爐學習,溫故知新。今天再次回顧總結一下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
由上面的驗證可以得出先前陳述的結論或者推論。
接下來通過簡單的代碼,回顧二維數組與指針的關系基礎知識。編寫代碼如下:
int a[12][31];
int *p;
int i;
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);
i = *(*(a + 4) + 7);
編譯後,運作結果如下:
value of p:00405630
size of a[4]: 124
value of i: 3
其中,a[4]的含義自然是代表數組a的下标為4的元素,而元素的為31個int類型對象。通過計算其占用的空間可以看出這一點。而進一步來看,其實a[4]應該是一個31個元素的數組的數組名。這樣,a[4]也就等同于這個數組的首位址。在程式中,我通過指針指派的方式輸出了這個位址數值。接下來的元素取值就值得去品味一下了:
第一次i取值:使用了數組名後面加中括号指明偏移來實作;
第二次i取值:進一步把第一步中的方式改成了指針取值的方式,通過首位址加偏移的方式。
第三次i取值:把疊代着的一個數組進一步展開。從最終的形式上看,這種方式比使用下标取值的簡寫方式要難了解不少。
最終i的三次輸出都是相同的,其實這也算是對三種方式等價的一個最基本的驗證。而把a指派給p是錯誤的,因為a的含義是一個指向“二維數組的指針”。在代碼中加入相應的代碼測試的時候,gcc編譯器會給出警告。不過,程式還是能夠編譯通過并運作。