a celé číslo s 0xFF
ponechává pouze nejméně významný bajt. Chcete-li například získat první bajt v short s
, můžete napsat s & 0xFF
. Toto je obvykle označováno jako „maskování“. Pokud byte1
je buď jednobajtový Typ (jako uint8_t
), nebo je již menší než 256 (a výsledkem jsou všechny nuly kromě nejméně významného bajtu) , není třeba maskovat vyšší bity, protože jsou již nulové.
viz odpověď tristopiaPatrick Schlüter níže, když můžete pracovat s podepsanými typy. Při provádění bitových operací doporučuji pracovat pouze s nepodepsanými typy.
pokud byte1
je 8bitový celočíselný Typ, pak je to zbytečné – pokud je to více než 8 bitů, v podstatě vám dá posledních 8 bitů hodnoty:
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
nebezpečí druhého výrazu přichází, pokud je typ byte1
char
. V takovém případě mohou mít některé implementace signed char
, což bude mít za následek rozšíření znaménka při hodnocení.
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);
vytiskne
value1=4224 1080 rightvalue2=65408 ff80 wrong!!
zkoušel jsem to na gcc v3. 4.6 na bitu Solaris SPARC 64 a výsledek je stejný s byte1
a byte2
deklarovaným jako char
.
TL; DR
maskování má zabránit implicitnímu rozšíření znaku.
upravit: zkontroloval jsem, je to stejné chování v C++.
EDIT2: jak bylo požadováno vysvětlení rozšíření znamení.Rozšíření znaku je důsledkem způsobu, jakým C hodnotí výrazy. V C je pravidlo zvané pravidlo propagace. C implicitně odevzdá všechny malé typy na int
před provedením hodnocení. Podívejme se, co se stane s naším výrazem:
unsigned short value2 = ((byte2 << 8) | byte1);
byte1
je proměnná obsahující bitový vzor 0xFF. Pokud je char
unsigned
, je tato hodnota interpretována jako 255, pokud je signed
je to -128. Při výpočtu C rozšíří hodnotu na velikost int
(obecně 16 nebo 32 bitů). To znamená, že pokud je proměnná unsigned
a ponecháme hodnotu 255, bitový vzor této hodnoty jako int
bude 0x000000FF. Pokud je signed
, chceme hodnotu -128, který bitový vzor je 0xFFFFFFFF. Značka byla rozšířena na velikost tempory použité k výpočtu.A tak oring dočasné přinese špatný výsledek.
v sestavě x86 se provádí instrukcí movsx
(movzx
pro nulovou extend). Ostatní CPU měly jiné pokyny pro to (6809 měl SEX
).