在 Android 系統底層開發中,經常需要在位操作、位圖管理或內存對齊場景下,快速計算「給定位數需要多少個 unsigned long 來存儲」。這是一個經典的向上取整除法問題,Linux 內核與 Android 源碼中通過宏 BITS_TO_LONGS 高效實現。
#define BITS_PER_LONG (sizeof(unsigned long) * 8) // 每個 long 的位數(32/64位平台自適應) #define BITS_TO_LONGS(x) (((x) + BITS_PER_LONG - 1) / BITS_PER_LONG)
unsigned long 的位寬(32位系統為32,64位系統為64)。(x + divisor - 1) / divisor 是整數運算中不使用浮點數實現向上取整的標準技巧。x 通常為編譯期常數或受限範圍變量,加法不會溢出 unsigned long 範圍。#include#define BITS_PER_LONG (sizeof(unsigned long) * 8) #define BITS_TO_LONGS(x) (((x) + BITS_PER_LONG - 1) / BITS_PER_LONG) int main() { // 假設 64位平台:BITS_PER_LONG = 64 int test_cases[] = {0, 1, 63, 64, 65, 127, 128, 1000}; int n = sizeof(test_cases) / sizeof(int); printf("平台 long 位寬:%d\n", BITS_PER_LONG); for (int i = 0; i < n; i++) { printf("bits=%-4d -> longs=%d\n", test_cases[i], BITS_TO_LONGS(test_cases[i])); } return 0; }
平台 long 位寬:64 bits=0 -> longs=0 bits=1 -> longs=1 bits=63 -> longs=1 bits=64 -> longs=1 bits=65 -> longs=2 bits=127 -> longs=2 bits=128 -> longs=2 bits=1000 -> longs=16
cpumask_t 類型內部即為 unsigned long 數組,宏用於計算數組大小。x 應為無符號類型或非負值,負數會導致邏輯錯誤。constexpr 函數替代宏,獲得類型安全與調試可見性。BYTES_TO_LONGS(x) = BITS_TO_LONGS((x)*8)。這個簡潔的宏體現了系統級 C 代碼「無分支、無浮點、跨平台、零開銷」的工程哲學,是底層開發者必備的工具箱組件。