次のコードでは:
short = ((byte2 << 8) | (byte1 & 0xFF))
&0xFF
の目的は何ですか?他のときとして私はそれが次のように書かれているのを見ます:
short = ((byte2 << 8) | byte1)
そしてそれもうまくいくようですか?
0xFF
で整数をアンディングすると、最下位バイトのみが残ります。たとえば、short s
の最初のバイトを取得するには、s & 0xFF
と書くことができます。これは通常、「マスキング」と呼ばれます。 byte1
がシングルバイトタイプ(uint8_t
など)であるか、すでに256未満である場合(その結果、最下位バイトを除くすべてゼロである場合)、上位バイトをマスクする必要はありません。それらは既にゼロであるため、ビット。
見る トリストピア署名付きのタイプを使用する場合の、以下のPatrickSchlüterの回答。ビット演算を行うときは、符号なしの型のみで作業することをお勧めします。
if byte1
は8ビット整数型であり、それは無意味です-8ビットを超える場合、基本的に値の最後の8ビットを提供します。
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
byte1
のタイプがchar
の場合、2番目の式の危険性が生じます。その場合、一部の実装ではsigned char
を使用でき、評価時に符号拡張になります。
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);
印刷します
value1=4224 1080 right
value2=65408 ff80 wrong!!
Solaris SPARC 64ビットのgcc v3.4.6で試しましたが、結果はbyte1
およびbyte2
がchar
として宣言されている場合と同じです。
TL; DR
マスキングは、暗黙的な符号拡張を回避することです。
[〜#〜] edit [〜#〜]:チェックしました。C++でも同じ動作です。
byte1
がバイト(8ビット)であると仮定すると、バイトと0xFFのビット単位のANDを実行すると、同じバイトが取得されます。
byte1
はbyte1 & 0xFF
と同じです
byte1
が01001101
の場合、byte1 & 0xFF = 01001101 & 11111111 = 01001101 = byte1
と言う
Byte1が4バイトの整数のような他のタイプの場合、0xFFとのビット単位のANDにより、byte1の最下位バイト(8ビット)が残ります。
byte1 & 0xff
は、byte1
の8つの最下位ビットのみがゼロ以外になることを保証します。
byte1
がすでに8ビットのみの符号なし型である場合(例:char
、またはほとんどの場合unsigned char
)、違いはありません/完全に不要です。
byte1
が符号付きまたは8ビットを超える型(たとえば、short
、int
、long
)、および8以外のビットの場合最下位が設定されている場合、違いがあります(つまり、他の変数でor
ingの前にそれらの上位ビットがゼロになるため、or
のこのオペランドは8つの最下位のみに影響します結果のビット)。
最初のバイトにないすべてのビットをクリアします
& 0xFF
自体は、バイトが(言語標準で許可されている)8ビットより長い場合にのみ、残りが無視されることを保証します。
そしてそれもうまくいくようですか?
結果がSHRT_MAX
を超えると、未定義の動作が発生します。その点で、両方とも同様に不十分に機能します。