<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
陣列是程式語言中常用的資料結構,然而在不同的環境下,其定義及初始化的方式也不盡相同。下面來講述一下C和Java中對於二維陣列定義的區別以及其背後的原理。
在C語言中,二維陣列的初始化可以省略行數,但不能省略列數;而在java中卻是正好相反的,即列數可以省略,而行數是不能省略的。為什麼會是這樣呢?首先我們來回顧一下C和Java中二維陣列的定義。
型別名 陣列名 [行數][列數];
例如:
int a[3][2]; /*表示定義了二維陣列a,3行2列,6個元素 */
可見,在C語言中,二維陣列的元素數量等於行數和列數的乘積,所以二維陣列一經定義,其被分配的記憶體大小就已經確定了。
因此,對於單純的定義二維陣列來說,其行和列都是不可省略的,一旦有省略,那麼在編譯時就會報“陣列記憶體大小不確定”的錯誤。
程式碼段及編譯結果如下圖所示:
int a[][5]; /*在定義陣列a時省略了行數*/
而我們所說的可以省略行數,是在對二維陣列初始化的時候,即在定義時給陣列元素賦初值的時候。要想編譯時不報錯,就需要讓編譯器知道該陣列佔用的記憶體空間,只不過在有省略的情況下就只能讓編譯器自己推斷出陣列佔用的記憶體空間了,那麼為什麼省略了行就能夠推斷出來,而省略了列就不可以呢?
這就要提到二維陣列元素在記憶體中的儲存方式了。C語言是按照“先行後列”的順序來儲存陣列的,即先儲存第0行的元素,然後是第1行的元素,以此類推。所以編譯器必須知道每行元素的個數,才能由初始化的結果推斷出行數,進而推斷出二維陣列所佔用的記憶體空間。而每行元素的個數正是二維陣列的列標。
在Java語言中對於二維陣列的定義稍微有些複雜,建立一個Java陣列需要三個步驟:宣告陣列、建立陣列空間、建立陣列元素並初始化。
其中初始化可以分為:靜態初始化和動態初始化。
int[][] arr = new int[][]{{1,2,3,6},{4,5},{7,8,9}}; 等價於 int arr[][] = {{1,2,3,6},{4,5},{7,8,9}};
int [][] arr3 = new int[4][3]; int [][] arr4 = new int[4][];
由動態初始化可以看出,在還沒有為二維陣列元素賦初值時,列下標是可以省略的。在這裡要宣告的一點是:C語言中二維陣列的每個元素都是大小相同的一維陣列,即如果把其中的各個元素鋪開,會是一個矩形;但在Java中並不要求每一個一維陣列的大小一致,所以也就不能在定義的時候說明列數。
(以相同的元素分別為C和Java中的二維陣列初始化)
int arr[3][4] = {{1,2,3,6},{4,5},{7,8,9}}; for(int i = 0; i < 3; i++){ for(int j = 0; j < 4; j++){ printf("%d ",arr[i][j]); } printf("n"); }
int[][] arr = new int[][]{{1,2,3,6},{4,5},{7,8,9}}; for(int i = 0; i < arr.length; i++){ for(int j = 0; j < arr[i].length; j++){ System.out.print(arr[i][j] + " "); } System.out.println(); }
那麼Java的二維陣列是怎樣儲存的呢?
Java二維陣列的陣列名儲存在棧中,堆裡面存放的是new出來的結構,比如具體的陣列元素。在定義二維陣列時,先在棧裡申請行數,然後等具體要用到哪一個一維陣列了再向堆申請記憶體。
所以在定義二維陣列時,若省略了列數,則可以看做是申請了若干個(行數)一維陣列,但是具體的一維陣列中的資料暫時是不知道的。
下面給出Java中二維陣列的記憶體解析圖:
由上圖可知:陣列arr1在定義時行標和列標都給出了,其定義的過程可以描述為:先在棧裡為arr1申請行數,即為arr1申請一片空間並把空間的首地址賦給arr1,相當於確定好了該二維陣列arr1中有三個元素,分別為三個一維陣列。而列標被定義出來就意味著為二維陣列的每個資料元素都分配好了記憶體空間,並把三個一維陣列的首地址傳了過去。對於arr1的各個資料元素,因為在定義的時候沒有賦初值,且是String型別,所以預設為null。
陣列arr2在定義時省略了列標,所以相當於只給出了arr2這個int型二維陣列的四個一維陣列元素,而沒有為這四個一維陣列賦初值。而因為arr2的四個元素都為參照資料型別(陣列),所以預設值為null。
arr2[1] = new int[5];
相當於為arr2的第二個元素指明瞭一塊記憶體空間,並把這塊空間的首地址賦給了arr2[1],arr2[1]的長度為5,元素型別為int型,又因為沒有為這個一維陣列賦初值,所以預設值為0。arr2[1][1] = 1;
的作用是把arr2[1]這個一維陣列的第二個元素賦值為1。arr2[2][2] = 1;
因為沒有為arr2的第三個元素分配記憶體空間,所以此時會報空指標異常。最後,再次回到Java中定義二維陣列時為什麼不能省略行數的問題。結合上述的記憶體解析,我們知道Java中的二維陣列是要先確立行數,進而才能確立列數,也就是要申請一片記憶體空間用來存放每個一位陣列的地址,然後才能為每個一維陣列分配記憶體空間。
以上為個人經驗,希望能給大家一個參考,也希望大家多多支援it145.com。
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45