數據結構與算法系列(二):關於數組,我想探討兩個問題

前言

時間與空間複雜度之後還會繼續深刻,目前能夠先擱置一邊。linux

​ 數據結構與算法中,最基本的兩個結構就是:數組、鏈表。兩者最大的區別在於:數組存儲地址是連續的,鏈表存儲地址不是(徹底)連續的。算法

​ 數組能夠說的沒有多少,一是由於簡單;二是由於有不少文章都講的很詳細。因此咱們再也不贅述,本片對數組引出的兩個問題進行探討:windows

  • 棧的生長方向以及數組的偏移
  • 大小端問題

棧的生長方向及數組偏移

引用一張 linux 進程內存結構的圖,其中 stack 棧的生長方向是向下生長的,也就是向低地址生長,即好比從 0x10008 - 0x00010。windows的棧也是向下生長。而咱們都知道,數組的元素和其對應的地址是往大增加的:數組

好比:int a[2] = {0}, 其中數組 a 的地址爲0x00010,那麼a[1] 的地址應該是 0x00010 + 1 * sizeof(int)數據結構

正是由於這種區別,考慮到以下的 C 程序 :佈局

#include <stdio.h>

int main() {
    int i = 5;
    int a[3] = {0};
    int j = 6;
	
    j = a[3];  // (1)
	
    printf("j is : %d", j); // (2)
    return 0;
}
複製代碼

運行後,輸出爲:ui

j is 5spa

爲何?操作系統

由於上述程序在執行 (1)以前,因爲(1)以前的變量都是局部變量,因此存儲在棧中。而上文說過了,棧的生長方向是向下的,且數組的元素地址是遞增的,因此(1)以前的內存(棧)佈局爲:翻譯

因此,當數組越界訪問 a[3] 時,就越界到了 i = 5 的位置,因此就會將 5 賦值給 j。

固然,實現上述結果的前提還有下面的兩點:

  • i 和 數組 a 類型相同,或者說兩者的類型佔用字節數相同
  • 所選用語言沒有對數組越界作出限制

這個程序還能夠進行擴展,留到下次進行分析。

大小端問題

上面是數組如何存儲的,那麼數組中的某一個元素又是如何存儲的?好比 int i = 5 ,其又是如何存儲的呢?

棧是一種數據結構,其本質是被操做系統管理的內存空間。變量 i 的存儲確定不是依靠操做系統來完成的,那麼是誰呢?

咱們寫好了某個語言的程序,程序須要轉換成機器語言即01010這種二進制語言纔可以被計算機識別,這一過程多是由編譯器來完成也多是由翻譯器來完成。

好比 i 轉換成機器語言後能夠用十六進制表示成 「0x00000005」(展開就是01010二進制),CPU須要讀取指令並執行,那麼當它收到這個數字時,又是如何解讀的呢?

假設 int 爲 4 字節大小,那麼一種解讀規則是:內存中的低位地址存儲 i 的高位字節,即:

0x00 0x1000
... ...
0x05 0x1003

這種存儲模式就稱爲 大端存儲

而另一種模式則反過來,以下表:

0x05 0x1000
... ...
0x00 0x1003

這種存儲模式就稱做爲 小端存儲

只有編譯器(解釋器)和 CPU 對於多字節數據的存儲模式相統一,纔可以正確執行程序。

拓展閱讀

  • 《深刻理解計算機系統》
  • 大小端
  • 進程模型
相關文章
相關標籤/搜索