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)