C語言數組入門之數組的聲明與二維數組的類比_C 語言

來源:互聯網
上載者:User

語言中指標與數組這兩個概念之間的聯絡是密不可分的,以至於如果不能理解一個概念,就無法徹底理解另一個概念。

C語言中的數組值得注意的地方有以下兩點:

C語言中只有一維數組,而且數組的大小必須在編譯期就作為一個常數確定下來。然而,C語言中數組的元素可以是任何類型的對象,當然也可以是另外一個數組。這樣,要“模擬”出一個多維陣列就不是一件難事。
對於一個數組,我們只能夠做兩件事:確定該數組的大小,以及獲得指向該數組下標為0的元素的指標。其他有關數組的操作,哪怕它們看上去是以數組下標進行運算的,實際上都是通過指標進行的。換句話說,任何一個數組下標運算都等同於一個對應的指標運算,因此我們完全可以依據指標行為定義數組下標的行為。
一旦我們徹底弄懂了這兩點以及它們所隱含的意思,那麼理解C語言的數組運算就不過是“小菜一碟”。如果不清楚上述兩點內容,那麼C語言數組運算就可能會給編程者帶來許多困惑。需要特別指出的是,編程者應該具備將數組運算與它們對應的指標運算融匯貫通的能力,在思考有關問題時大腦中對這兩種運算能夠自如切換。毫無滯礙。

任何程式設計語言中都內建有索引運算,在C語言中索引運算是以指標算術的形式來定義的。

如何聲明一個數組

要理解C語言中數組的運作機制,我們首先必須理解如何聲明一個數組,例如:

int a[3];

這個語句聲明了a是一個擁有了3個整型元素的數組,類似的,

struct{ int p[4]; double x;}b[17];

聲明了b是一個擁有17個元素的數組,其中每個元素都是一個結構,該結構中包括了一個擁有4個整形元素的數組(命名為p)和一個雙精確度類型的變數(命名為x)。

現在考慮下面的例子:

int calendar[12][31];

這個語句聲明了calendar是一個數組,該數組擁有12個數群組類型的元素,其中每個元素都是擁有31個整型元素的數組(而不是一個擁有31個數群組類型的元素的數組,其中每個元素又是一個擁有12個整型數組元素的數組)因此sizeof(calendar)的值是372(31*12)與sizeof(int)的乘積。

如果calendar不是用於sizeof的運算元,而是用於其他的場合,那麼calendar總是被替換成一個指向calendar數組的起始元素的指標。要理解上面這句話的含義,我們首先必須理解有關指標的一些細節。

二維數組類比
*a即數組a中下標為0的元素的引用。例如,我們可以這樣寫:

*a=84;

這個語句將數組a中下標為0的元素的值設定為84.同樣道理,*(a+1)數組a中下標為1的的元素的引用,以此類推,概而言之,*(a+i)即數組中下標為i的元素的引用,這種寫法是如此常用,因此被簡記為a[i].

正是這一概念讓C語言新手難於理解,實際上,由於a+i與i+a的含義一樣,因此a[i]和i[a]也具有同樣的含義。也許某些組合語言程式員會發現後一種寫法很熟悉,但我們絕對不推薦這種寫法。

現在我們可以考慮二維數組了,正如前面所討論的,它實際上是以數組為元素的數組,儘管我們也可以完全依據指標編寫操縱一維數組的程式,這樣做在一維情形下並不困難,但是對於二維數組從記法上的便利性來說採用下述形式就幾乎是不可替代了。還有,如果我們僅僅使用指標來操縱二維數組,我們將不得不與C語言中最為“晦暗不明”的部分打交道,並常常遭遇到潛伏著的編譯器bug。

讓我們回過頭來再看幾個聲明:

int calendar[12][31];int *pint i;

然後考一考自己,calendar[4]的含義是什嗎?

因為calendar是一個有著12個數群組類型元素的數組,它的每個數群組類型元素又是一個有著31個整型數組,所以calendar[4]是 calendar數組的第五個元素,是calendar數組中12個有著31個整型元素的數組之一,因此calendar[4]的行為也就表現一個有著31個整形元素的數組的行為,例如sizeof(calendar[4])的結果是31與sizeof(int)的乘積。

p=calendar[4];

這個語句使指標p指向了數組calendar[4]中下標為0的元素。如果calendar[4]是一個數組,我們當然可以通過下標的形式來指定這個數組中的元素,就像下面這樣:

i = calendar[4][7];

我們確實也可以這樣做。還是與前面類似的道理,這個語句可以寫成下面這樣而運算式的意思保持不變:

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

這個語句還可以進一步寫成:

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

從這裡我們不難發現,用方括弧的下標形式很明顯地要比指標來表達簡便得多。下面我們再看:

p = calendar;

這個語句是非法的,因為calendar是一個二維數組,即數組的數組,在此處的上下文中使用calendar名稱會將其轉化為一個指向數組的指標,而p是一個指向整型變數的指標,這個語句試圖將一個類型的指標賦值給另一種類型的指標,所以是非法的。

很顯然,我們需要一種聲明指向數組的指標的方法,經過了前面對類似問題不厭其煩的討論,構造出下面的語句應該不需要廢多大力氣:

int (*ap)[31];

這個語句的效果是,聲明了*ap是一個擁有三十一個整型元素的數組ap就是一個指向這樣的數組的指標,因而我們可以這樣寫:

int(*monthp)[31];Monthp = calendar;

這樣,monthp將指向數組calendar的第一個元素,也就是數組calendar的12個有著31個元素的數群組類型元素之一。

假定在新的一年開始時,我們需要清空calendar數組,用下標形式可以很容易做到:

int month;for(month=0;month < 12;month++){ int day;  for(day=0; day < 31;day++)   calendar[month][day]=0;}

上面的程式碼片段如果才用指標應該如何表示呢?我們很容易地把 calendar[month][day]=0; 表示為*(*(calendar+month)+day)=0;

但是真正有關的部分是哪些呢?

如果指標monthp指向一個擁有31個整型元素的數組,而calendar的元素也是一個擁有31個整型元素的數組,因此就像是在其他情況中我們可以使用一個指標遍曆一個數組一樣,這裡我們同樣可以使用指標monthp以步進的方式遍曆數組calendar:

int (*monthp)[31];for(monthp=calendar;monthp < &calendar[12];monthp++){ int *dayp; for(dayp=*monthp;dayp < &(*monthp)[31];dayp++) *dayp=0;}

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.