誰かが私にこの機能を説明してもらえますか?
最下位 n ビットが 1 に設定されたマスク。
元:
n = 6 --> 0x2F, n = 17 --> 0x1FFFF // これらがまったくわかりません。特に n = 6 --> 0x2F
また、マスクとは何ですか?
誰かが私にこの機能を説明してもらえますか?
最下位 n ビットが 1 に設定されたマスク。
元:
n = 6 --> 0x2F, n = 17 --> 0x1FFFF // これらがまったくわかりません。特に n = 6 --> 0x2F
また、マスクとは何ですか?
通常の方法は、 を取り、それを左ビット1
にシフトすることです。n
それはあなたに次のようなものを与えるでしょう00100000
: 次に、それから 1 を引きます。これにより、設定されているビットがクリアされ、下位ビットがすべて設定されます。この場合、次のようになります00011111
。
マスクは通常、ビット演算で使用されます。特にand
. 上記のマスクを使用して、存在する可能性のある他のものから分離された 5 つの最下位ビットを取得します。これは、多くの場合、完全に別個の無関係な数量やフラグを表すビットを含む単一のハードウェア レジスタを持つハードウェアを扱う場合に特に一般的です。
マスクは、別の整数値とのビット単位の AND、OR、XOR などである整数値の一般的な用語です。
たとえば、int 変数の最下位 8 桁を抽出する場合は、次のようにしますvariable & 0xFF
。0xFF はマスクです。
同様に、ビット 0 と 8 を設定する場合はvariable | 0x101
、0x101 がマスクです。
または、同じビットを反転したい場合はvariable ^ 0x101
、 0x101 がマスクです。
ケースのマスクを生成するには、マスクに 1 を追加すると (すべての最下位ビットが 1 に設定され、残りが 0 に設定されているマスク)、次のべき乗である値が得られるという単純な数学的事実を利用する必要があります。 2.
したがって、最も近い 2 の累乗を生成する場合、それから 1 を引いてマスクを取得できます。
2 の正の累乗は<<
、C の左シフト演算子を使用して簡単に生成できます。
したがって、1 << n
2 nが得られます。バイナリでは、0 を含む 10...0n
です。
(1 << n) - 1
n
最下位ビットが 1 に設定されたマスクを生成します。
ここで、左シフトのオーバーフローに注意する必要があります。C (および C++) では、変数のビット位置と同じ数だけ変数を左に合法的にシフトすることはできないため、int が 32 ビットの場合、1<<32
結果はundefined behavior
. 符号付き整数のオーバーフローも回避する必要があるため、符号なしの値を使用する必要があります1u << 31
。
最新の x86 プロセッサ (特に BLSMSK) での BMI 命令の出現により、この質問が 2012 年に行われて以来、正確性とパフォーマンスの両方について、これを達成するための最良の方法が変更されました。
古いプロセッサとの下位互換性を維持しながら、この問題にアプローチする良い方法を次に示します。
この方法は正しいですが、現在の上位の回答では、エッジ ケースで未定義の動作が発生します。
Clang と GCC は、BMI 命令を使用して最適化できる場合、gen_mask() を 2 つの操作に凝縮します。ハードウェアをサポートしている場合は、BMI 命令のコンパイラ フラグを必ず追加してください。
-mbmi -mbmi2
#include <inttypes.h>
#include <stdio.h>
uint64_t gen_mask(const uint_fast8_t msb) {
const uint64_t src = (uint64_t)1 << msb;
return (src - 1) ^ src;
}
int main() {
uint_fast8_t msb;
for (msb = 0; msb < 64; ++msb) {
printf("%016" PRIx64 "\n", gen_mask(msb));
}
return 0;
}
あなたの最初の例は0x3f
.
0x3f
は 2 進数の数値の 16 進数表記である63
ため111111
、最後の 6 ビット (最下位 6 ビット) は に設定され1
ます。
次の小さな C プログラムは、正しいマスクを計算します。
#include <stdarg.h>
#include <stdio.h>
int mask_for_n_bits(int n)
{
int mask = 0;
for (int i = 0; i < n; ++i)
mask |= 1 << i;
return mask;
}
int main (int argc, char const *argv[])
{
printf("6: 0x%x\n17: 0x%x\n", mask_for_n_bits(6), mask_for_n_bits(17));
return 0;
}
0x2F
は0010 1111
2 進数です - これ0x3f
は0011 1111
、2 進数で、最下位 6 ビットが設定された である必要があります。
同様に、17 の最下位ビットが設定された 2 進数です0x1FFFF
。0001 1111 1111 1111 1111
「マスク」とは、 のようなビット単位の演算子を使用して別の値と組み合わせたり、他の値のビットを&
個別に設定、設定解除、反転、変更しないままにすることを目的とした値です。|
^
たとえば、演算子を使用して mask0x2F
を何らかの値と組み合わせると、結果の最下位 6 ビットを除くすべてがゼロになり、それらの 6 ビットは value から変更されずにコピーされます。n
&
n
マスクの場合、&
マスク内のバイナリ0
は「結果ビットを無条件に 0 に1
設定する」ことを意味し、「結果ビットを入力値ビットに設定する」ことを意味します。|
マスクの場合、マスク0
内の は結果ビットを入力ビットに1
設定し、 は結果ビットを無条件に に設定します1
。^
マスクの場合、0
は結果ビットを入力ビットに1
設定し、 は結果ビットを の補数に設定します。入力ビット。