在驅動程式開發、記憶體管理、DMA 傳輸、快取行對齊等場景,頻繁需要將數值「向上對齊」到特定邊界。最常見的是8 位元組對齊(64 位元系統常見)與2 的 N 次方對齊。本文提供無分支、高效能的通用演算法。
// 對齊到 2^N 的倍數
#define ALIGN_UP(val, n) (((val) + (1 << (n)) - 1) & ~((1 << (n)) - 1))
// 等價寫法(移位版,避免位移溢位風險)
#define ALIGN_UP_SHIFT(val, n) ((((val) + (1u << (n)) - 1) >> (n)) << (n))
// 方法一:位元遮罩
#define ALIGN_8(val) (((val) + 7) & ~7)
// 方法二:移位組合(原文提供)
#define ALIGN_8_SHIFT(val) (((val) + 8) >> 3) << 3
原理:(val + alignment - 1) 確保「剛好對齊」的值不變,「未對齊」的值進位到下一個邊界,再 & ~(alignment-1) 清除低位。
| val | val+7 | 二進位 | & ~7 | 結果 |
|---|---|---|---|---|
| 0 | 7 | 0000 0111 | 0 | 0 ✓ |
| 1 | 8 | 0000 1000 | 8 | 8 ✓ |
| 7 | 14 | 0000 1110 | 8 | 8 ✓ |
| 8 | 15 | 0000 1111 | 8 | 8 ✓ |
| 9 | 16 | 0001 0000 | 16 | 16 ✓ |
((val + 8) >> 3) << 3
val + 8:向上偏移一個對齊單位>> 3:除以 8 (捨去餘數)<< 3:乘以 8 (還原對齊位址)| val | val+8 | >>3 | <<3 | 結果 |
|---|---|---|---|---|
| 0 | 8 | 1 | 8 | 8 |
| 1 | 9 | 1 | 8 | 8 ✓ |
| 7 | 15 | 1 | 8 | 8 ✓ |
| 8 | 16 | 2 | 16 | 16 |
| 9 | 17 | 2 | 16 | 16 ✓ |
注意:此方法對「已對齊」的值會進位到下一個邊界 (val=0→8, val=8→16)。若需「已對齊保持不變」,請用 ((val + 7) >> 3) << 3 或方法一。
// 模板函數版 (C++,型別安全)
template <typename T>
constexpr T align_up(T value, size_t alignment) {
static_assert((alignment & (alignment - 1)) == 0, "alignment must be power of 2");
return (value + alignment - 1) & ~(alignment - 1);
}
// C 巨集版
#define ALIGN_UP_POW2(val, align) (((val) + (align) - 1) & ~((align) - 1))
offsetof 計算時確保成員對齊AND、ARM BIC)%),位元運算零延遲constexpr 可在編譯期完成計算,零執行期開銷「對齊到 2 的 N 次方」是位元運算的經典應用。掌握 (val + align - 1) & ~(align - 1) 通用公式,並理解移位版本的邊界行為差異,能讓你在嵌入式、系統程式、高效能運算中遊刃有餘。記住:**對齊值必須是 2 的冪次**,否則公式失效。