en een geheel getal met 0xFF
laat alleen de minst significante byte over. Om bijvoorbeeld de eerste byte in een short s
te krijgen, kunt u s & 0xFF
schrijven. Dit wordt meestal aangeduid als “maskeren”. Als byte1
een enkel bytetype is (zoals uint8_t
) of al kleiner is dan 256 (en als gevolg daarvan alle nullen zijn behalve de minst significante byte) is het niet nodig om de hogere bits te maskeren, omdat ze al nul zijn.
zie het antwoord van tristopiaPatrick Schlüter hieronder wanneer u mogelijk met ondertekende types werkt. Bij het doen van bitwise operaties, adviseer ik alleen te werken met unsigned types.
als byte1
een 8-bit integer type is dan is het zinloos-als het meer dan 8 bits is zal het in wezen de laatste 8 bits van de waarde geven:
0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 & 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 ------------------------------- 0 0 0 0 0 0 0 0 0 1 0 1 0 1 0 1
het gevaar van de tweede uitdrukking komt als het type byte1
char
is. In dat geval kunnen sommige implementaties het signed char
hebben, wat resulteert in sign extension bij het evalueren.
signed char byte1 = 0x80;signed char byte2 = 0x10;unsigned short value1 = ((byte2 << 8) | (byte1 & 0xFF));unsigned short value2 = ((byte2 << 8) | byte1);printf("value1=%hu %hx\n", value1, value1);printf("value2=%hu %hx\n", value2, value2);
zal
value1=4224 1080 rightvalue2=65408 ff80 wrong!!
afdrukken ik heb het geprobeerd op gcc v3. 4.6 op Solaris SPARC 64 bit en het resultaat is hetzelfde met byte1
en byte2
gedeclareerd als char
.
TL; DR
het maskeren dient om impliciete tekenuitbreiding te vermijden.
bewerken: ik heb het gecontroleerd, Het is hetzelfde gedrag in C++.
EDIT2: zoals gevraagd uitleg van sign extension.Sign extensie is een gevolg van de manier waarop C uitdrukkingen evalueert. Er is een regel in C genaamd promotie regel. C zal impliciet alle kleine types op int
werpen alvorens de evaluatie uit te voeren. Laten we eens kijken wat er gebeurt met onze expressie:
unsigned short value2 = ((byte2 << 8) | byte1);
byte1
is een variabele die bitpatroon 0xFF bevat. Indien char
unsigned
wordt deze waarde geïnterpreteerd als 255, indien signed
is het -128. Bij het uitvoeren van de berekening, zal C de waarde uitbreiden tot een int
Grootte (16 of 32 bits in het algemeen). Dit betekent dat als de variabele unsigned
is en we de waarde 255 behouden, het bit-patroon van die waarde als int
0x000000FF zal zijn. Als het signed
is willen we de waarde -128 welk bit patroon 0xFFFFFFFF is. Het teken werd uitgebreid tot de grootte van de tempory gebruikt om de berekening te doen.En dus oring de tijdelijke zal het verkeerde resultaat opleveren.
bij x86-assemblage wordt dit gedaan met de instructie movsx
(movzx
voor de nuluitbreiding). Andere CPU ‘ s hadden daar andere instructies voor (6809 had SEX
).