și un număr întreg cu 0xFF
lasă doar octetul cel mai puțin semnificativ. De exemplu, pentru a obține primul octet într-un short s
, puteți scrie s & 0xFF
. Acest lucru este de obicei denumit „mascare”. Dacă byte1
este fie un singur tip de octet (cum ar fi uint8_t
), fie este deja mai mic de 256 (și ca rezultat sunt toate zerourile, cu excepția octetului cel mai puțin semnificativ), nu este nevoie să mascați biții mai mari, deoarece sunt deja zero.
a se vedea tristopiaPatrick Schl răspunsul de mai jos, atunci când s-ar putea fi de lucru cu tipuri semnate. Când efectuați operații pe biți, vă recomand să lucrați numai cu tipuri nesemnate.
dacă byte1
este un tip întreg pe 8 biți, atunci este inutil – dacă este mai mult de 8 biți, vă va oferi în esență ultimii 8 biți ai valorii:
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
pericolul celei de-a doua expresii vine dacă tipul de byte1
este char
. În acest caz, unele implementări îl pot avea signed char
, ceea ce va duce la extinderea semnului la evaluare.
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);
va imprima
value1=4224 1080 rightvalue2=65408 ff80 wrong!!
am încercat-o pe gcc v3.4.6 pe Solaris SPARC 64 biți și rezultatul este același cu byte1
și byte2
declarat ca char
.
TL;DR
mascarea este de a evita extinderea semn implicit.
EDIT: am verificat, este același comportament în c++.
EDIT2: după cum se solicită explicația extensiei semnului.Extensia semnului este o consecință a modului în care c evaluează expresiile. Există o regulă în C numită regulă de promovare. C va arunca implicit toate tipurile mici la int
înainte de a face evaluarea. Să vedem ce se întâmplă cu expresia noastră:
unsigned short value2 = ((byte2 << 8) | byte1);
byte1
este o variabilă care conține modelul de biți 0xFF. Dacă char
este unsigned
această valoare este interpretată ca 255, dacă este signed
este -128. Când efectuați calculul, C va extinde valoarea la o dimensiune int
(în general 16 sau 32 de biți). Aceasta înseamnă că dacă variabila este unsigned
și vom păstra valoarea 255, modelul de biți al acelei valori ca int
va fi 0x000000FF. Dacă este signed
vrem valoarea -128 care model de biți este 0xfffffffff. Semnul a fost extins la dimensiunea tempory utilizate pentru a face calculul.Și astfel oring temporar va produce rezultatul greșit.
la asamblarea x86 se face cu instrucțiuneamovsx
(movzx
pentru extinderea zero). Alte CPU-uri aveau alte instrucțiuni pentru asta (6809 avea SEX
).