Digamos que tienes un número:0x1006
Por alguna razón, desea alinearlo con un 4
límite de bytes.
Con un límite de 4 bytes, sabe que los valores alineados son 0x1000
, 0x1004
, 0x1008
, etc. Entonces también conoce el valor alineado de 0x1006
es 0x1008
.
¿Cómo obtendrías 0x1008
? ? La máscara de alineación para el valor de alineación 4
es (4 - 1) = 0x03
Ahora 0x1006 + 0x03 = 0x1009
y 0x1009 & ~0x03 = 0x1008
Esta operación es la __ALIGN_MASK
macro.
Si desea pasar el valor 4
(la alineación) en lugar de directamente 0x03
(la máscara de alineación), tienes el ALIGN
macro
#define ALIGN(x,a) __ALIGN_MASK(x,(typeof(x))(a)-1)
la alineación, a
, se convierte en x
de tipo, y luego se resta uno. La alineación debe ser una potencia de 2, por lo que da como resultado un número del patrón de bits 00..011..11
de x
de tipo, la máscara (k
1 si a = 2^k
).
Entonces
#define __ALIGN_MASK(x,mask) (((x)+(mask))&~(mask))
agrega el valor de la máscara a x
, de modo que (x)+ (mask)
es al menos tan grande como el múltiplo más pequeño de la alineación que no es menor que x
y menor que el siguiente múltiplo mayor. Luego el bit a bit y con el complemento de la máscara reduce ese número a ese múltiplo de la alineación.
Para máscaras de la forma 2^k - 1
, el cálculo
(x + mask) & ~mask
es lo mismo que
(x + 2^k - 1) - ((x + 2^k - 1) % (2^k))
o
((x + 2^k - 1)/(2^k)) * (2^k)