Supponi di avere un numero:0x1006
Per qualche motivo vuoi allinearlo a un 4
limite di byte.
Con un limite di 4 byte, sai che i valori allineati sono 0x1000
, 0x1004
, 0x1008
, ecc. Quindi conosci anche il valore allineato di 0x1006
è 0x1008
.
Come otterresti 0x1008
? La maschera di allineamento per il valore di allineamento 4
è (4 - 1) = 0x03
Ora 0x1006 + 0x03 = 0x1009
e 0x1009 & ~0x03 = 0x1008
Questa operazione è il __ALIGN_MASK
macro.
Se vuoi passare il valore 4
(l'allineamento) invece che direttamente 0x03
(la maschera di allineamento), hai il ALIGN
macro
#define ALIGN(x,a) __ALIGN_MASK(x,(typeof(x))(a)-1)
l'allineamento, a
, viene trasmesso a x
's type, quindi ne viene sottratto uno. L'allineamento dovrebbe essere una potenza di 2, in modo da ottenere un numero del modello di bit 00..011..11
di x
, la maschera (k
1s se a = 2^k
).
Allora
#define __ALIGN_MASK(x,mask) (((x)+(mask))&~(mask))
aggiunge il valore della maschera a x
, in modo che (x)+ (mask)
è grande almeno quanto il multiplo più piccolo dell'allineamento che non è minore di x
e minore del successivo multiplo maggiore. Quindi il bit per bit e con il complemento della maschera riduce quel numero a quel multiplo dell'allineamento.
Per maschere della forma 2^k - 1
, il calcolo
(x + mask) & ~mask
è uguale a
(x + 2^k - 1) - ((x + 2^k - 1) % (2^k))
o
((x + 2^k - 1)/(2^k)) * (2^k)