計(jì)算機(jī)內(nèi)存是以字節(jié)(Byte)為單位劃分的瘾敢,理論上CPU可以訪問任意編號(hào)的字節(jié)粤铭,但實(shí)際情況并非如此辫塌。
CPU 通過地址總線來訪問內(nèi)存览妖,一次能處理幾個(gè)字節(jié)的數(shù)據(jù),就命令地址總線讀取幾個(gè)字節(jié)的數(shù)據(jù)蔚叨。32 位的 CPU 一次可以處理4個(gè)字節(jié)的數(shù)據(jù)棺克,那么每次就從內(nèi)存讀取4個(gè)字節(jié)的數(shù)據(jù)症概;少了浪費(fèi)主頻,多了沒有用但荤。64位的處理器也是這個(gè)道理罗岖,每次讀取8個(gè)字節(jié)。
以32位的CPU為例腹躁,實(shí)際尋址的步長為4個(gè)字節(jié)桑包,也就是只對編號(hào)為 4 的倍數(shù)的內(nèi)存尋址,例如 0纺非、4哑了、8、12烧颖、1000 等弱左,而不會(huì)對編號(hào)為 1、3炕淮、11拆火、1001 的內(nèi)存尋址。如下圖所示:
這樣做可以以最快的速度尋址:不遺漏一個(gè)字節(jié)鳖悠,也不重復(fù)對一個(gè)字節(jié)尋址榜掌。
對于程序來說优妙,一個(gè)變量最好位于一個(gè)尋址步長的范圍內(nèi)乘综,這樣一次就可以讀取到變量的值;如果跨步長存儲(chǔ)套硼,就需要讀取兩次卡辰,然后再拼接數(shù)據(jù),效率顯然降低了邪意。
例如一個(gè) int 類型的數(shù)據(jù)在內(nèi)存中占據(jù)4個(gè)字節(jié)九妈,如果地址為 8,那么很好辦雾鬼,對編號(hào)為 8 的內(nèi)存尋址一次就可以萌朱。如果編號(hào)為 10,就比較麻煩策菜,CPU需要先對編號(hào)為 8 的內(nèi)存尋址晶疼,讀取4個(gè)字節(jié),得到該數(shù)據(jù)的前半部分又憨,然后再對編號(hào)為 12 的內(nèi)存尋址翠霍,讀取4個(gè)字節(jié),得到該數(shù)據(jù)的后半部分蠢莺,再將這兩部分拼接起來寒匙,才能取得數(shù)據(jù)的值。
將一個(gè)數(shù)據(jù)盡量放在一個(gè)步長之內(nèi)躏将,避免跨步長存儲(chǔ)锄弱,這稱為內(nèi)存對齊考蕾。在32位編譯模式下,默認(rèn)以4字節(jié)對齊会宪;在64位編譯模式下辕翰,默認(rèn)以8字節(jié)對齊。
關(guān)于Go語言的內(nèi)存對齊示例請看這里:
Go 內(nèi)存對齊-結(jié)構(gòu)體