52

次のコードでは:

short = ((byte2 << 8) | (byte1 & 0xFF))

目的は&0xFF何ですか?他の時々私はそれが次のように書かれているのを見るので:

short = ((byte2 << 8) | byte1)

そして、それもうまくいくようですか?

4

7 に答える 7

42

整数をAndすると、0xFF最下位バイトのみが残ります。たとえば、の最初のバイトを取得するにはshort s、と書くことができますs & 0xFF。これは通常、「マスキング」と呼ばれます。byte1がシングルバイトタイプ(のようなuint8_t)であるか、すでに256未満である場合(したがって、最下位バイトを除いてすべてゼロである場合)、上位ビットはすでにゼロであるため、マスクする必要はありません。

署名されたタイプで作業している可能性がある場合は、以下のtristopiaPatrickSchlüterの回答を参照してください。ビット単位の演算を行うときは、符号なしの型のみを使用することをお勧めします。

于 2013-02-05T17:16:44.120 に答える
42

が 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
于 2013-02-05T17:18:59.560 に答える
24

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 で試してみましたが、結果は と同じで、byte1byte2宣言されてい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)。

于 2013-02-05T17:51:54.160 に答える
10

あなたがバイト(8ビット)であると仮定するbyte1と、バイトと0xFFのビットごとのANDを実行すると、同じバイトが得られます。

byte1と同じですbyte1 & 0xFF

と言うbyte101001101byte1 & 0xFF = 01001101 & 11111111 = 01001101 = byte1

byte1 が 4 バイトの整数などの他の型である場合、0xFF とのビットごとの AND により、byte1 の最下位バイト (8 ビット) が残ります。

于 2013-02-05T17:17:30.987 に答える
5

byte1 & 0xff最下位 8 ビットのみbyte1が非ゼロになることが保証されます。

ifbyte1がすでに 8 ビットしかない符号なし型 (たとえば、char場合によっては、またはunsigned charほとんど) である場合、違いはありません/完全に不要です。

が符号付きまたは 8ビットをbyte1超える型 (たとえばshort、したがって、 のこのオペランドは、結果の最下位 8 ビットのみに影響します)。intlongoror

于 2013-02-05T17:18:46.083 に答える
2

最初のバイトにないすべてのビットをクリアします

于 2013-02-05T17:17:20.507 に答える
0

& 0xFF単独では、バイトが 8 ビット (言語標準で許可されている) よりも長い場合、残りが無視されることのみが保証されます。

そして、それもうまくいくようですか?

結果が より大きい場合SHRT_MAX、未定義の動作が発生します。その点で、どちらも同じようにうまく機能しません。

于 2013-02-05T17:29:54.587 に答える