és ha egy egész számot 0xFF
– mal jelölünk, akkor csak a legkevésbé jelentős bájt marad. Például, ha az első bájtot short s
– ban szeretné megkapni, írhat s & 0xFF
– ot. Ezt általában “maszkolásnak”nevezik. Ha a byte1
vagy egy bájtos Típus (mint a uint8_t
), vagy már kevesebb, mint 256 (és ennek eredményeként az összes nulla, kivéve a legkevésbé jelentős bájtot), akkor nincs szükség a magasabb bitek elfedésére, mivel már nulla.
lásd alább a Tristopiapatrick Schl! Dzctter válaszát, ha esetleg aláírt típusokkal dolgozik. Bitenkénti műveletek végrehajtásakor azt javaslom, hogy csak aláíratlan típusokkal dolgozzon.
ha a byte1
8 bites egész típusú, akkor értelmetlen – ha több mint 8 Bit, akkor lényegében megadja az érték utolsó 8 bitjét:
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
a második kifejezés veszélye akkor következik be, ha a byte1
típusa char
. Ebben az esetben egyes implementációkban lehet signed char
, ami a jel kiterjesztését eredményezi az értékelés során.
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);
fog nyomtatni
value1=4224 1080 rightvalue2=65408 ff80 wrong!!
próbáltam a gcc v3.4.6 A Solaris SPARC 64 biten, és az eredmény ugyanaz a byte1
és byte2
char
.
TL;DR
a maszkolás az implicit jel kiterjesztésének elkerülése.
EDIT: ellenőriztem, ez ugyanaz a viselkedés a C++ – ban.
EDIT2: a jel kiterjesztésének kért magyarázata szerint.A jelkiterjesztés annak a következménye, ahogyan a C értékeli a kifejezéseket. A C-ben van egy szabály, az úgynevezett promóciós szabály. C implicit módon az összes kis típust int
– re dobja az értékelés elvégzése előtt. Lássuk, mi történik a kifejezésünkkel:
unsigned short value2 = ((byte2 << 8) | byte1);
byte1
egy 0xFF bitmintát tartalmazó változó. Ha char
jelentése unsigned
, akkor ezt az értéket 255-nek kell értelmezni, ha signed
-128. A számítás során a C kiterjeszti az értéket int
méretre (általában 16 vagy 32 bit). Ez azt jelenti, hogy ha a változó unsigned
és megtartjuk a 255 értéket, akkor ennek az értéknek a bitmintája int
lesz 0x000000FF. Ha ez signed
, akkor a -128 értéket akarjuk, amely bitminta 0xFFFFFFFF. A jelet kiterjesztették a számításhoz használt tempory méretére.Így az ideiglenes oring rossz eredményt hoz.
az x86 szerelvényen a movsx
utasítással történik (movzx
a nulla kiterjesztéshez). Más CPU-knak más utasításai voltak erre (6809 volt SEX
).