Angenommen, Sie haben eine Nummer:0x1006
Aus bestimmten Gründen möchten Sie es an einem 4
ausrichten Byte-Grenze.
Bei einer 4-Byte-Grenze wissen Sie, dass ausgerichtete Werte 0x1000
sind , 0x1004
, 0x1008
, usw. Sie kennen dann auch den ausgerichteten Wert von 0x1006
ist 0x1008
.
Wie würden Sie 0x1008
bekommen ? Die Ausrichtungsmaske für den Ausrichtungswert 4
ist (4 - 1) = 0x03
Jetzt 0x1006 + 0x03 = 0x1009
und 0x1009 & ~0x03 = 0x1008
Diese Operation ist der __ALIGN_MASK
Makro.
Wenn Sie den Wert 4
übergeben möchten (die Ausrichtung) statt direkt 0x03
(die Ausrichtungsmaske), haben Sie die ALIGN
Makro
#define ALIGN(x,a) __ALIGN_MASK(x,(typeof(x))(a)-1)
die Ausrichtung, a
, wird in x
umgewandelt 's Typ, und dann wird eins subtrahiert. Die Ausrichtung sollte eine Potenz von 2 sein, so dass sich eine Zahl des Bitmusters 00..011..11
ergibt von x
's Typ, die Maske (k
1s wenn a = 2^k
).
Dann
#define __ALIGN_MASK(x,mask) (((x)+(mask))&~(mask))
fügt den Wert der Maske zu x
hinzu , sodass (x)+ (mask)
ist mindestens so groß wie das kleinste Vielfache der Ausrichtung, das nicht kleiner als x
ist und kleiner als das nächstgrößere Vielfache. Dann wird diese Zahl bitweise und mit dem Komplement der Maske auf das Vielfache der Ausrichtung reduziert.
Für Masken der Form 2^k - 1
, die Berechnung
(x + mask) & ~mask
ist dasselbe wie
(x + 2^k - 1) - ((x + 2^k - 1) % (2^k))
oder
((x + 2^k - 1)/(2^k)) * (2^k)