再下來我們要講一個很重要的觀念就是
那個陣列,尤其是多維陣列它的記憶體配置 問題,這對我們寫程式來將非常重要,因為我有了解說
陣列是怎麼樣配置記憶體的,那你才能了解說真正那個將來再學習指標
跟那個比較高維的那個陣列的時候,你才會了解中間互相的關係是什麼?所以我們先舉一個很- 簡單的範例,
就是說,我們現在有一個矩陣,它有三維,第一個維度呢, 是
2,第二個維度是 3,第三個維度是 4,所以總共呢有 24 個
元素。那我們首先呢就印這些東西出來。
這些東西就是說 a[0][0] 到底是什麼? a[0][0],a[0][0][0] 到底 是什麼? a[0][0] 是什麼?a[0]
是什麼?那 a 又是什麼?那這些東西它的大小是什麼? 我們先把它印出來,然後呢我們再把每一個元素,在這裡
按照 i,j,k,就是由左到右它的各個維度
一直去調變,然後把它的位址印出來,那注意到這裡呢,我們是在 最後一個維度,這個是 0 到 3,0,1,2,3。
就是這 4 個維度,用完了以後呢,中間有空一格,用完以後我們又換行。這樣的話
比較方便清楚。然後呢,這整個事情呢,中間再換行,意思就是說 這前面那個
i 跟後面那個 i 中間也換一行,這樣的話也方便我們來看,
那之後呢,我們會印一些 奇怪的事情,比如說像這個到底是什麼?
如果說是這樣印,如果是 a[i][1] 這到底是什麼? 那跟 a[i][1]
值的關係到底是什麼?那這個我們等一下會說明,或者說 a[i]
是什麼? a[i] 的值跟 a[i] 到底有什麼關係,最後我們回到說
a 跟 a 的值到底有什麼關係?這是第二個我們要 印出來的東西。所以,我們在這邊要
那個講解的第二個關係就是到底記憶體大小跟 那個 array 是什麼關係?那我麼知道
a[0][0][0] 這個是一個四個位元組的整數,所以它的
sizeof 是多少呢?自然是 4,那 a[0][0] 是什麼意思呢? 那 a[0][0] 呢,是一個 4
乘,4個,4 個位元組的, 整數所組成的陣列,那是為什麼?因為這個維度我沒寫,沒寫的意思就是說所有
前面是兩個零的那都包含在這個集合裡頭,所以它是有 4 個位元,所以它應該是 16。
那 a 是包含所有的,那所以就是全部加起來。這個很難懂,那
我們就用一個比較簡單的例子來說明這件事情,我們把它想象成為房子,OK,所以這個房子- 是什麼意思呢?
我們現在有兩排房子,兩排房子,所以第一個維度就代表你是在第幾排,你的房子在第幾排。
第二個維度呢,就是說每一排房子有幾層。
那我們現在這個維度呢有三層,那這個維度就是說在每 一排每一層裡頭到底有幾戶?就是你家到底是哪一排哪一
層的哪一戶。那用這三個坐標呢就可以知道說你家在哪裡了。所以我們在 這邊呢就是說
a 是什麼呢,a 事實上你在記憶體裡頭看到呢
就是這個東西啊,[0][0][0],[0][0][1],[0][0][2],[0]- [0][3],這樣子一直下去。
那 a[0] 是什麼呢?a[0] 是所有
第一個注標為零的元 素,所以你可以把它想象就是說所有在第一排的房子,
我們就記得我們這邊有兩排,因為第一個維度是排,第幾排,有幾排房子,所以這邊看起來像- 是第一排房子。
第一排房子裡頭呢有 3 層,每一層呢有 4 戶,
那這樣的話呢所有 a[0] 的事實上就是,那當你說 a[0]
是什麼意思? 當你說 a[0] 就是這些人,就是所有第一排的房子,那
a[0][0] 是什麼意思呢?a[0][0] 就是說你在第 0 排,
也就是在第一層的房子的集合,那這樣的話就有 4 戶,因為 a[0][0] 就是
包括這些人,所以 a[0] 就是前面第一個是 0 的,a[0][0] 就是前面有兩個是 0 的。
好,有了這個觀念以後呢我們就很清楚了,所以各位可以把它想象成房子,第一個呢代表排,- 第二個代表
層,第三個代表戶,這樣。記憶體擺放的順序就是這樣,a[0][0][0],a[0][- 0][1],
它是由右邊開始變動,由右邊開始變動,就跟你車子或者是
就跟你車子的碼表一樣,它是從右邊開始跑,你可以把它想象成碼表。
那碼錶以後,就 0 到 9,那排完以後跳回下一個。這有點像是什麼?
有點像,你看這個房子,也就是說,在第 0 層, 第 0
排,第 0 層,有 4 戶,0,1,2,3 再下來是什麼,再下來就是
第 0 排的第 1 層的第 0,所以這邊就相當於你可以把它想象成像
是一個進位,這樣子進位的觀念,所以進位到這裡來了,那到這裡呢,就是說第 0
排, 第 2 層第 3 戶再下來是哪一個?再下來就是 第 1
排的第 0 層第 0 戶,所以在 C 裡頭它是 陣列是這樣排的,它的陣列是這樣排的,
那擺放方式就是要先放第一個矩陣,不要把它想象成矩陣,你想象成這一排房屋就好了, 再放第二排的房子,那每一排的房子呢,先放第
0 層,再放第 1 層,再放第 2 層,因為我們有三層。
那每一層呢先放第 0 戶,然後再放第 1 戶,再放第 2 戶,
再放第 3 戶,最後這個東西你看你就可以理解了啊。
這 C 是怎麼擺放,在陣列裡頭怎麼擺放記憶體的。所以說我們再仔細看
它事實上就是這個樣子,你如果了解了這個觀念以後呢,你就會很容易算出來位址啊,如果一- 開始位址是這樣的話,
這個就是這樣,那每次跳 16,為什麼跳 16 呢,是因為它每一個 位址呢是
4 個位元組,這邊我用虛線畫
代表 4 位元組,所以這整個是一個 4 個位元組的整數。那每一排 每一層有 4 戶,所以這樣每一層就跳 16。
好,我們根據以上的討論,我們可以歸納出來說到底 一個多維陣列它的位置怎麼算,那算法就是這樣,你把它起始
位置找出來啊,你剛開始要放哪裡,先記好,然後呢 按照我們剛才的例子,就是
i乘上3乘上4,也就 乘上12, j乘上4再加上k呢就是,再乘上
4 就是位址,這個為什麼是這樣子呢? 因為你如果把它想成,把
a 當做一維陣列的話,它裡頭第幾個怎麼算?你看啊 我是
i 是表示它是第幾排,那每一排有 12 戶,為什麼一排有 12 戶呢,因為它有
3乘4 一層有 4 戶,所以你每次跳一個 i 就要跳 12, 那每一次跳一個
j 要跳多少?要跳 4,那是為什麼?那是因為一層有 4 戶。到最後加上 k,k
就是一層裡頭 你到底在哪裡?那當然就加上去,這整個為什麼要乘
4 呢,這是因為每一戶 有 4 個位元組,因為我們這邊是用 integer 每一個 integer
是 4 個 bytes, 你現在整個算起來就知道說它到底要從哪裡開始。
那所以我們很容易看說這個到 這個是要跳
4,這個倒這個是要跳 4。那到底第幾戶怎麼看呢?我們隨便找一個來看,比如說
比如說 1,2, 1,2 是第幾個呢? 我們知道它是
1,所以它一開始這個iii它已經跳了 12 了,因為它是在第二排, 再加上這個
1,這個 1 什麼呢?再乘上 4,所以我是 12 加 4 再加上 2。
12 加 4 再加上 2,這是為什麼呢,因為 1
告訴我說,它要先跳這麼多,2 這個維度
一開始這每一個要跳那個 12,那這個呢要跳
4,所以我已經跳了 16 了,那最後再 跳一個 2,就是
8,就是 18。所以我知道這是第 18 個元素。
這怎麼看呢? 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,
15,16,17,18,所以這個確實是 18,那這樣你就可以很容易的由這些 i,j,k,
算出來說如果這些房子是擺在一個一維陣列裡頭,也就是記憶體裡頭,那記憶體像是一個一- 維陣列,
那它到底在哪一戶?在哪一戶呢,你再乘上 4。
因為這一戶有四個位元組,再加上這個起始位址,你就很容易知道說你這個記憶體是在哪裡呢?
那如果是用比較具體的數學來表示
的話,就是像這樣子,那各位可以仔細的去研究這個內容,那事實上所表達的意思就是這樣, i
呢就乘後面兩個維度,j 呢乘後面一個維度,那 k 後面沒有維度就直接乘 1,這裡是一樣的道理。
所以我元素 i,j,k,在這裡是用
k1,k2,一直到 kn 的具體位址呢可以表為上式,那我們現在就可以知道說
當初我們說陣列的注標由零開始道理在哪裡呢?因為如果由零開始的話,
這個轉換非常的容易的。如果你由一開始的話那個轉換還要減一再乘上,減一再乘上, 那很麻煩,如果直接從
0 開始的話,你是直接可以拿這個 i,j,k,直接乘 12 跟乘 4 加起來。
那就是你位於第幾個,各位可以試著研究一下,如果說這些注標都從 1
開始的話,這個位址會蠻,這個位 址計算會蠻複雜的,所以在 C
裡頭呢我們事實上, 是由,注標是由 0 開始,這可以大部分簡化這些位址的計算。
那在這邊就大致上像剛剛那些 那些和你想的一樣,就是說,任何一個陣列的
a[i] 它有三列,也就是說任何 一個講成房子的話,就是一排房子
有三層分別是第 0 層,第 1 層跟第 2 層。
好,那由這樣來看就可以很容易理解說這到底
剛才那些關係是什麼?所以每一列的位址就是第一位,第一個元素的位址,所以 a[i][0]
的位址就是 a[i][0][0] 的位址,這什麼意思呢?就是說你是 哪一排的第幾層的位址
那事實上是這樣就是哪一排那一層的第零戶的位址。
各位可以理解就是說一層從哪裡開始呢?一層由它 那一層的第一戶開始,那這個,這個,這個
這個各位可以回去想一想,從那個對,那 a[i] 是什麼意思呢?a[i] 就是說
你那一排房子從哪裡開始? 那如果你說那一排的房子可以開始,當然是從那一排房子的第零層的第零戶開始,
所以這兩個位址是一樣的,這兩個位址一樣,各位可以回去看這個圖。
所以 a[0] 從哪裡開始呢?a[0] 從這裡開始。
所以 a 從哪裡開始呢?從這裡開始。所以 a[0][0] 從哪裡開始呢?也從這裡開始。
那如果是a[1] 從哪裡開始呢?那 a[1] 就從這裡開始。
如果這邊是 a[1] 的話,就是從這邊開始, 如果是
a[1][1] 的話就是從這邊開始。
[聲音] [空白_录音]