と0xffは何をしますか?

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

符号付き型を使用している場合は、以下のtristopiaPatrick Schlüterの回答を参照してください。 ビット単位の操作を行う場合は、符号なし型のみを使用することをお勧めします。

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

2番目の式の危険性は、byte1の型がcharの場合に発生します。 その場合、いくつかの実装ではsigned charを持つことができ、評価時に符号拡張が発生します。Gcc v3.4で試してみましたが、

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 rightvalue2=65408 ff80 wrong!!

を出力します。結果は、byte1byte2charとして宣言されていても同じです。

TL;DR

マスキングは、暗黙の符号拡張を避けることです。編集:私はチェックしました、それはC++で同じ動作です。

EDIT2:要求された記号拡張の説明として。符号拡張は、Cが式を評価する方法の結果です。 Cには昇格ルールと呼ばれるルールがあります。 Cは、評価を行う前に、すべての小さな型を暗黙的にintキャストします。 私たちの表現に何が起こるか見てみましょう:

unsigned short value2 = ((byte2 << 8) | byte1);

byte1 は、ビットパターン0xffを含む変数です。 charunsignedの場合、その値は255と解釈され、signedの場合は-128と解釈されます。 計算を行うとき、Cは値をintサイズ(通常は16ビットまたは32ビット)に拡張します。 これは、変数がunsignedで値255を保持する場合、その値のビットパターンはintとして0x000000ffになることを意味します。 それがsignedの場合、ビットパターンが0xFFFFFFFFである値-128が必要です。 符号は、計算を行うために使用される一時的なサイズに拡張されました。したがって、一時的なoringは間違った結果をもたらします。

x86アセンブリでは、movsx命令(ゼロ拡張の場合はmovzx)で行われます。 他のCPUにはそのための他の命令がありました(6809にはSEXがありました)。

コメントを残す

メールアドレスが公開されることはありません。