計算機內存是以字節(Byte)為單位劃分的,理論上CPU可以訪問任意編號的字節,但實際情況并非如此。
CPU 通過地址總線來訪問內存,一次能處理幾個字節的數據,就命令地址總線讀取幾個字節的數據。32 位的 CPU 一次可以處理4個字節的數據,那么每次就從內存讀取4個字節的數據;少了浪費主頻,多了沒有用。64位的處理器也是這個道理,每次讀取8個字節。
以32位的CPU為例,實際尋址的步長為4個字節,也就是只對編號為 4 的倍數的內存尋址,例如 0、4、8、12、1000 等,而不會對編號為 1、3、11、1001 的內存尋址。如下圖所示:
內存尋址示意圖.jpeg
這樣做可以以最快的速度尋址:不遺漏一個字節,也不重復對一個字節尋址。
對于程序來說,一個變量最好位于一個尋址步長的范圍內,這樣一次就可以讀取到變量的值;如果跨步長存儲,就需要讀取兩次,然后再拼接數據,效率顯然降低了。
例如一個 int 類型的數據在內存中占據4個字節,如果地址為 8,那么很好辦,對編號為 8 的內存尋址一次就可以。如果編號為 10,就比較麻煩,CPU需要先對編號為 8 的內存尋址,讀取4個字節,得到該數據的前半部分,然后再對編號為 12 的內存尋址,讀取4個字節,得到該數據的后半部分,再將這兩部分拼接起來,才能取得數據的值。
將一個數據盡量放在一個步長之內,避免跨步長存儲,這稱為內存對齊。在32位編譯模式下,默認以4字節對齊;在64位編譯模式下,默認以8字節對齊。
關于Go語言的內存對齊示例請看這里:
Go 內存對齊-結構體