Supposons que vous ayez un numéro :0x1006
Pour certaines raisons, vous souhaitez l'aligner sur un 4
limite d'octets.
Avec une limite de 4 octets, vous savez que les valeurs alignées sont 0x1000
, 0x1004
, 0x1008
, etc.Vous connaissez alors également la valeur alignée de 0x1006
est 0x1008
.
Comment obtiendriez-vous 0x1008
? Le masque d'alignement pour la valeur d'alignement 4
est (4 - 1) = 0x03
Maintenant 0x1006 + 0x03 = 0x1009
et 0x1009 & ~0x03 = 0x1008
Cette opération est le __ALIGN_MASK
macro.
Si vous voulez passer la valeur 4
(l'alignement) au lieu de directement 0x03
(le masque d'alignement), vous avez le ALIGN
macro
#define ALIGN(x,a) __ALIGN_MASK(x,(typeof(x))(a)-1)
l'alignement, a
, est converti en x
's type, puis un est soustrait. L'alignement doit être une puissance de 2, de sorte qu'il en résulte un nombre de la configuration binaire 00..011..11
de x
de type, le masque (k
1s si a = 2^k
).
Alors
#define __ALIGN_MASK(x,mask) (((x)+(mask))&~(mask))
ajoute la valeur du masque à x
, de sorte que (x)+ (mask)
est au moins aussi grand que le plus petit multiple de l'alignement qui n'est pas inférieur à x
et plus petit que le prochain plus grand multiple. Ensuite, le bit à bit et avec le complément du masque réduit ce nombre à ce multiple de l'alignement.
Pour les masques de la forme 2^k - 1
, le calcul
(x + mask) & ~mask
est le même que
(x + 2^k - 1) - ((x + 2^k - 1) % (2^k))
ou
((x + 2^k - 1)/(2^k)) * (2^k)