數據結構對齊

數據結構對齊是代碼編譯後在記憶體的布局與使用方式。包括三方面內容:數據對齊、數據結構填充(padding)與包入(packing)。

簡介

現代計算機一般是32比特或64比特地址對齊,如果要訪問的變數沒有對齊,可能會觸發匯流排錯誤。

當數據小於計算機的字(word)尺寸,可能把幾個數據元素放在一個字中,稱為 包入(packing)。

許多程式語言自動處理數據結構對齊。Ada語言,PL/I,Pascal,某些C語言與C++實現,D語言,Rust,與彙編語言允許特別控制對齊的方式。

定義

記憶體地址a被稱為n位元組對齊,當a是n的倍數(n應是2的冪)。

一次記憶體訪問被稱為對齊的,當被訪問的數據長度為n位元組且該數據地址為n位元組對齊。如果記憶體未對齊,稱作misaligned。顯然,位元組訪問總是對齊的。

記憶體指針是對齊的,如果它所指的數據是對齊的。指向聚合數據(aggregate data,如struct或數組)是對齊的,若且唯若它的每個組成數據是對齊的。

x86體系結構

x86體系架構最初是不要求記憶體對齊。一些SSE2指令要求數據是128比特(16位元組)對齊。有些CPU指令用於未對齊訪問如MOVDQU。讀寫記憶體操作僅在對齊時才是原子的。

C語言struct在x86上的對齊

C語言數據結構內的成員先後順序不能改變。

常見的C語言編譯器在32比特x86上, double是8位元組對齊,但Linux上是4位元組對齊(編譯選項-malign-double實現8位元組對齊)。

一些編譯器(Microsoft,Borland,GNU,等等)使用#pragmadirective指定對齊的包入(packing)。例如:

這個結構在32位系統的大小為6位元組。

預設packing與#pragma pack

Microsoft編譯器的項目預設packing(編譯選項/Zp)與#pragma pack指令。#pragma pack指令僅能減少packing尺寸。

數組步長

數組步長(stride of an array,也稱increment, pitch或step size)是程式設計時,相鄰數組元素在記憶體中的開始地址的距離,度量單位可以是位元組或者數組元素個數。步長不可小於數組元素的尺寸,但可以大於,表示有填充的位元組。

數組步長如果等於數組元素的尺寸,則數組在記憶體中是連續的。這可稱為 單位步長(unit stride)。非單位步長適用於二維數組或多維數組。

類型雙關

類型雙關是計算機科學的術語,指任何編程技術能顛覆或者繞過一門程式設計語言的類型系統,以達成在形式語言內部難以甚至不可能實現的效果。

C語言與C++語言,語法結構如類型轉換與union,以及C++增加的reinterpret_cast運算符,用於實現類型雙關。

Pascal語言使用records與variants來按照多種方法處理特定數據類型。

相關詞條

熱門詞條

聯絡我們