Řekněme, že máte číslo:0x1006
Z některých důvodů jej chcete zarovnat na 4
hranice bajtů.
Se 4bajtovou hranicí víte, že zarovnané hodnoty jsou 0x1000
, 0x1004
, 0x1008
, atd. Pak také znáte zarovnanou hodnotu 0x1006
je 0x1008
.
Jak byste získali 0x1008
? Maska zarovnání pro hodnotu zarovnání 4
je (4 - 1) = 0x03
Nyní 0x1006 + 0x03 = 0x1009
a 0x1009 & ~0x03 = 0x1008
Tato operace je __ALIGN_MASK
makro.
Pokud chcete předat hodnotu 4
(zarovnání) místo přímo 0x03
(maska zarovnání), máte ALIGN
makro
#define ALIGN(x,a) __ALIGN_MASK(x,(typeof(x))(a)-1)
zarovnání, a
, je přetypován na x
's type a pak se jedna odečte. Zarovnání by mělo být mocninou 2, takže výsledkem bude číslo bitového vzoru 00..011..11
z x
's type, maska (k
1s if a = 2^k
).
Potom
#define __ALIGN_MASK(x,mask) (((x)+(mask))&~(mask))
přidá hodnotu masky na x
, takže (x)+ (mask)
je alespoň tak velký jako nejmenší násobek zarovnání, který není menší než x
a menší než nejbližší větší násobek. Poté bitové a s doplňkem masky sníží toto číslo na tento násobek zarovnání.
Pro masky ve tvaru 2^k - 1
, výpočet
(x + mask) & ~mask
je stejný jako
(x + 2^k - 1) - ((x + 2^k - 1) % (2^k))
nebo
((x + 2^k - 1)/(2^k)) * (2^k)