次のコードでは:
short = ((byte2 << 8) | (byte1 & 0xFF))
目的は&0xFF何ですか?他の時々私はそれが次のように書かれているのを見るので:
short = ((byte2 << 8) | byte1)
そして、それもうまくいくようですか?
次のコードでは:
short = ((byte2 << 8) | (byte1 & 0xFF))
目的は&0xFF何ですか?他の時々私はそれが次のように書かれているのを見るので:
short = ((byte2 << 8) | byte1)
そして、それもうまくいくようですか?
整数をAndすると、0xFF最下位バイトのみが残ります。たとえば、の最初のバイトを取得するにはshort s、と書くことができますs & 0xFF。これは通常、「マスキング」と呼ばれます。byte1がシングルバイトタイプ(のようなuint8_t)であるか、すでに256未満である場合(したがって、最下位バイトを除いてすべてゼロである場合)、上位ビットはすでにゼロであるため、マスクする必要はありません。
署名されたタイプで作業している可能性がある場合は、以下のtristopiaPatrickSchlüterの回答を参照してください。ビット単位の演算を行うときは、符号なしの型のみを使用することをお勧めします。
が 8 ビット整数型の場合byte1は無意味です。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の型がの場合、2 番目の式の危険性が生じcharます。その場合、一部の実装ではそれを持つことができ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 ++でも同じ動作です。
EDIT2 : 符号拡張の説明を要求されたとおり。符号拡張は、C が式を評価する方法の結果です。C にはプロモーション ルールと呼ばれるルールがあります。intC は、評価を行う前に、すべての小さな型を暗黙的にキャストします。式がどうなるか見てみましょう:
unsigned short value2 = ((byte2 << 8) | byte1);
byte1ビットパターン 0xFF を含む変数です。その値が 255 として解釈される場合charは、 -128 です。計算を行うとき、C は値をサイズ (通常は 16 または 32 ビット)に拡張します。これは、変数が255 の値を保持する場合、その値のビットパターンは0x000000FF になることを意味します。その場合、ビット パターンが 0xFFFFFFFF である値 -128 が必要です。記号は、計算を行うために使用されるテンポのサイズに拡張されました。したがって、一時的な oring は間違った結果をもたらします。unsignedsignedintunsignedintsigned
x86 アセンブリでは、movsx命令 (movzxゼロ拡張用) で実行されます。他のCPUにはそのための他の命令がありました(6809にはありましたSEX)。
あなたがバイト(8ビット)であると仮定するbyte1と、バイトと0xFFのビットごとのANDを実行すると、同じバイトが得られます。
byte1と同じですbyte1 & 0xFF
と言うbyte1と01001101、byte1 & 0xFF = 01001101 & 11111111 = 01001101 = byte1
byte1 が 4 バイトの整数などの他の型である場合、0xFF とのビットごとの AND により、byte1 の最下位バイト (8 ビット) が残ります。
のbyte1 & 0xff最下位 8 ビットのみbyte1が非ゼロになることが保証されます。
ifbyte1がすでに 8 ビットしかない符号なし型 (たとえば、char場合によっては、またはunsigned charほとんど) である場合、違いはありません/完全に不要です。
が符号付きまたは 8ビットをbyte1超える型 (たとえばshort、したがって、 のこのオペランドは、結果の最下位 8 ビットのみに影響します)。intlongoror
最初のバイトにないすべてのビットをクリアします
& 0xFF単独では、バイトが 8 ビット (言語標準で許可されている) よりも長い場合、残りが無視されることのみが保証されます。
そして、それもうまくいくようですか?
結果が より大きい場合SHRT_MAX、未定義の動作が発生します。その点で、どちらも同じようにうまく機能しません。