ja kokonaisluku, jolla on 0xFF
, jättää jäljelle vain vähiten merkitsevän tavun. Esimerkiksi ensimmäisen tavun saa short s
kirjoittamalla s & 0xFF
. Tämä on tyypillisesti kutsutaan ”masking”. Jos byte1
on joko yksittäinen tavutyyppi (kuten uint8_t
) tai on jo alle 256 (ja sen seurauksena kaikki nollat lukuun ottamatta vähiten merkitsevää tavua), ei tarvitse peittää korkeampia bittejä, koska ne ovat jo nollia.
Katso tristopiaPatrick Schlüterin vastaus alta, milloin signeerattujen tyyppien kanssa voi työskennellä. Kun teet bitwise operaatioita, suosittelen työskentelyä vain allekirjoittamattomien tyyppien kanssa.
jos byte1
on 8-bittinen kokonaisluku, niin se on turhaa – jos se on enemmän kuin 8 bittiä, se antaa periaatteessa arvon viimeiset 8 bittiä:
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
toisen lausekkeen vaara tulee, jos Tyyppi byte1
on char
. Tällöin joissain toteutuksissa se voi olla signed char
, jolloin sitä arvioitaessa päädytään merkkilaajennukseen.
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);
tulostetaan
value1=4224 1080 rightvalue2=65408 ff80 wrong!!
kokeilin sitä gcc: llä v3. 4.6 Solaris SPARCILLA 64 bittiä ja tulos on sama byte1
ja byte2
ilmoitettu char
.
TL; DR
peittämisellä pyritään välttämään implisiittinen merkin laajentaminen.
EDIT: tarkistin, se on sama käyttäytyminen C++: ssa.
EDIT2: pyydetyn selityksen mukainen kyltin laajennus.Sign extension on seurausta tavasta, jolla C arvioi ilmaisuja. C: ssä on sääntö nimeltä ylennyssääntö. C laskee implisiittisesti kaikki pienet tyypit arvoon int
ennen arvioinnin tekemistä. Katsotaan, mitä tapahtuu ilmaisullemme:
unsigned short value2 = ((byte2 << 8) | byte1);
byte1
on muuttuja, joka sisältää bittikuvion 0xFF. Jos char
on unsigned
tuo arvo tulkitaan arvoksi 255, jos se on signed
se on -128. Laskentaa tehtäessä C laajentaa arvon int
kokoiseksi (yleensä 16 tai 32 bittiä). Tämä tarkoittaa, että jos muuttuja on unsigned
ja pidämme arvon 255, kyseisen arvon bittikuvio arvona int
on 0x000000ff. Jos se on signed
haluamme arvon -128 mikä bittikuvio on 0xFFFFFFFF. Merkki laajennettiin laskutoimituksessa käytetyn temporyn kokoiseksi.Ja siten tilapäisen välittäminen tuottaa väärän tuloksen.
x86-kokoonpanolla se tehdään movsx
– ohjeella (movzx
nollapidennykselle). Muissa suorittimissa oli siihen muita ohjeita (6809: llä oli SEX
).