程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C >> 關於C >> C語法陷阱:C語言的二維數組模擬

C語法陷阱:C語言的二維數組模擬

編輯:關於C

從前面的討論中,我們不難得出一個推論,*a即數組a中下標為0的元素的引用。例如,我們可以這樣寫:

1 *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。

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

1 int calendar[12][31];
2 int *p
3 int i;
然後考一考自己,calendar[4]的含義是什麼?

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

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

1 i = calendar[4][7];
我們確實也可以這樣做。還是與前面類似的道理,這個語句可以寫成下面這樣而表達式的意思保持不變:

1 i = *(calendar[4]+7);
這個語句還可以進一步寫成:

1 i = *(*(calendar+4)+7);
從這裡我們不難發現,用方括號的下標形式很明顯地要比指針來表達簡便得多。下面我們再看:

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

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

1 int (*ap)[31];
這個語句的效果是,聲明了*ap是一個擁有三十一個整型元素的數組ap就是一個指向這樣的數組的指針,因而我們可以這樣寫:

1 int(*monthp)[31];
2 Monthp = calendar;
這樣,monthp將指向數組calendar的第一個元素,也就是數組calendar的12個有著31個元素的數組類型元素之一。

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

1 int month;

3 for(month=0;month < 12;month++){
4     int day;
5     for(day=0; day < 31;day++)
6         calendar[month][day]=0;
7 }
上面的代碼段如果才用指針應該如何表示呢?我們很容易地把 calendar[month][day]=0; 表示為*(*(calendar+month)+day)=0;

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

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

1 int (*monthp)[31];
2 for(monthp=calendar;monthp < &calendar[12];monthp++){
3     int *dayp;
4     for(dayp=*monthp;dayp < &(*monthp)[31];dayp++)
5     *dayp=0;
6 }
到目前為止,我們一路行來幾乎是“如履薄冰”,而且已經走得很遠,在我們跌跤之前,最好趁早懸崖勒馬。盡管本節中最後一個例子是合法的ANSI C程序,但是作者還有找到一個能夠讓該程序順利通過編譯的編譯器(譯注:現在大多數的c編譯器能夠接受上面例子中的代碼)。上面例子的討論雖然有些偏離本書的主題,但是這個例子能夠很好地揭示出C語言中數組與指針之間的獨特的關系,從而更清楚明白地闡述這兩個概念。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved