/// Align downwards. Returns the greatest x with alignment `align`
/// so that x <= addr. The alignment must be a power of 2.
pub fn align_down(addr: usize, align: usize) -> usize {
    if align.is_power_of_two() {
        addr & !(align - 1)
    } else if align == 0 {
        addr
    } else {
        panic!("`align` must be a power of 2");
    }
}

/// Align upwards. Returns the smallest x with alignment `align`
/// so that x >= addr. The alignment must be a power of 2.
pub fn align_up(addr: usize, align: usize) -> usize {
    align_down(addr + align - 1, align)
}

align的值是内存对齐的参数,是2的倍数{1, 2, 4, 8, 16, ...}

使用二进制表示align,{1, 10, 100, 1000, 10000, ...}

align-1得到{0, 01, 011, 0111, 01111, ...}

!(align-1)得到{...11111, ...11110, ...11100, ...11000, ...10000, ...}

addr & !(align-1)会将addr的高位(左边视为地位,右边视为高位)关闭(0视作关闭,1视作打开)

align_up的处理逻辑如下面两张图,为了在已经对齐的情况下节省内存节省内存做了减1操作

addr未对齐的情况 addr已经对齐对齐的情况