och ett heltal med 0xFF
lämnar endast den minst signifikanta byten. Till exempel, för att få den första byten i en short s
kan du skriva s & 0xFF
. Detta kallas vanligtvis ”maskering”. Om byte1
antingen är en enda byte-typ (som uint8_t
) eller redan är mindre än 256 (och som ett resultat är alla nollor utom den minst signifikanta byten) behöver man inte maskera de högre bitarna, eftersom de redan är noll.
se tristopiaPatrick Schl Jacobters svar nedan när du kanske arbetar med signerade typer. När du gör bitvis operationer rekommenderar jag att du bara arbetar med osignerade typer.
om byte1
är en 8-bitars heltalstyp är det meningslöst – om det är mer än 8 bitar kommer det i huvudsak att ge dig de sista 8 bitarna av värdet:
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
faren för det andra uttrycket kommer om typen byte1
är char
. I så fall kan vissa implementeringar ha det signed char
, vilket kommer att resultera i teckenförlängning vid utvärdering.
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);
kommer att skriva ut
value1=4224 1080 rightvalue2=65408 ff80 wrong!!
jag försökte det på gcc v3.4.6 på Solaris SPARC 64 bit och resultatet är detsamma med byte1
och byte2
deklarerade som char
.
TL;DR
maskeringen är att undvika implicit teckenförlängning.
redigera: jag kollade, det är samma beteende i C++.
EDIT2: som begärd förklaring av teckenförlängning.Teckenförlängning är en följd av hur C utvärderar uttryck. Det finns en regel i C som kallas promotion rule. C kommer implicit att kasta alla små typer till int
innan utvärderingen görs. Låt oss se vad som händer med vårt uttryck:
unsigned short value2 = ((byte2 << 8) | byte1);
byte1
är en variabel som innehåller bitmönster 0xFF. Om char
är unsigned
tolkas värdet som 255, om det är signed
är det -128. När du gör beräkningen kommer C att utöka värdet till en int
storlek (16 eller 32 bitar i allmänhet). Det betyder att om variabeln är unsigned
och vi kommer att behålla värdet 255, kommer bitmönstret för det värdet som int
att vara 0x000000FF. Om det är signed
vill vi ha värdet -128 vilket bitmönster är 0xFFFFFFFF. Tecknet utvidgades till storleken på tempory som användes för att göra beräkningen.Och sålunda kommer det tillfälliga att ge fel resultat.
på x86-montering görs det med movsx
– instruktionen (movzx
för nollförlängningen). Andra CPU: er hade andra instruktioner för det (6809 hade SEX
).