次のコードでは:
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 にはプロモーション ルールと呼ばれるルールがあります。int
C は、評価を行う前に、すべての小さな型を暗黙的にキャストします。式がどうなるか見てみましょう:
unsigned short value2 = ((byte2 << 8) | byte1);
byte1
ビットパターン 0xFF を含む変数です。その値が 255 として解釈される場合char
は、 -128 です。計算を行うとき、C は値をサイズ (通常は 16 または 32 ビット)に拡張します。これは、変数が255 の値を保持する場合、その値のビットパターンは0x000000FF になることを意味します。その場合、ビット パターンが 0xFFFFFFFF である値 -128 が必要です。記号は、計算を行うために使用されるテンポのサイズに拡張されました。したがって、一時的な oring は間違った結果をもたらします。unsigned
signed
int
unsigned
int
signed
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 ビットのみに影響します)。int
long
or
or
最初のバイトにないすべてのビットをクリアします
& 0xFF
単独では、バイトが 8 ビット (言語標準で許可されている) よりも長い場合、残りが無視されることのみが保証されます。
そして、それもうまくいくようですか?
結果が より大きい場合SHRT_MAX
、未定義の動作が発生します。その点で、どちらも同じようにうまく機能しません。