首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

C 語言位元組對齊原理:x86 CPU 存取未對齊記憶體的多次讀取機制

     編輯:程式設計綜合問答

現象描述

32 位 CPU,`int` (4 bytes) 自然對齊地址為 4 的倍數 (0x0, 0x4, 0x8...)。

  • 地址 0x2 (未對齊) → 需 2 次記憶體讀取:`[0x0-0x3]` + `[0x4-0x7]`,取出後拼湊。
  • 地址 0x3 (未對齊) → 需 3 次讀取:`[0x0-0x3]` (取 1 byte) + `[0x4-0x7]` (取 2 bytes) + `[0x8-0xB]` (取 1 byte)。

硬體根本原因

**x86 CPU 資料總線寬度 32 bits (4 bytes),記憶體控制器以 4-byte 為最小讀取單位 (自然對齊邊界)。**

  • CPU 發出讀取指令時,地址總線低 2 位必為 00 (即 4 的倍數)。
  • 若請求地址非 4 的倍數,CPU 內部微程式會自動拆分為多次對齊讀取,再由移位/遮罩指令組合結果。
  • 這完全由硬體透明完成,軟體無感知,但**效能下降** (多時脈、佔用總線)。

為何 0x2 讀兩次、0x3 讀三次?


// 記憶體內容 (每格 1 byte)
Addr: 0x0  0x1  0x2  0x3  0x4  0x5  0x6  0x7  0x8  0x9 ...
Val:  AA  BB  CC  DD  EE  FF  00  11  22  33 ...

// int *p = (int*)0x2;  // 欲讀 0x2-0x5 (CC DD EE FF)
// CPU 實際操作:
Read 1: Addr 0x0, 取 4 bytes → AA BB CC DD  (暫存)
Read 2: Addr 0x4, 取 4 bytes → EE FF 00 11  (暫存)
// 組合: 取 Read1[2:3] (CC DD) + Read2[0:1] (EE FF) → CC DD EE FF

// int *p = (int*)0x3;  // 欲讀 0x3-0x6 (DD EE FF 00)
Read 1: Addr 0x0 → AA BB CC DD  (取 DD)
Read 2: Addr 0x4 → EE FF 00 11  (取 EE FF)
Read 3: Addr 0x8 → 22 33 ...    (取 00)
// 組合: DD + EE FF + 00 → DD EE FF 00

結論

x86 允許未對齊存取但效能損耗大;ARM/MIPS 等架構直接拋出 Alignment Fault。編譯器預設對齊結構體成員 (`#pragma pack` 可調整),**嚴禁強制轉型指標到未對齊地址** (如 `(int*)0x2`)。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved