8

私は自分が持っていたデータ圧縮のアイデアを実装しようとしています。テスト データの大規模なコーパスに対して実行することを想像しているので、C でコーディングすることを考えていました (私は主に Ruby などのスクリプト言語の経験があり、 Tcl.)

C に関する O'Reilly の「牛」の本を調べてみると、単純な「char」または「int」型の変数のビットに単純にインデックスを付けることはできないことに気付きました。ビットごとの比較と演算子を実行したいからです。

この認識で私は正しいですか?ビットを表すために列挙型を使用する (そしてこれらの配列を作成し、char との間で変換する関数を作成する) ことは合理的ですか? もしそうなら、そのような型と関数は標準ライブラリで定義されていますか? 他の(より良い?)アプローチはありますか?誰かが私に指摘できるサンプルコードはどこかにありますか?

ありがとう -

4

9 に答える 9

10

Kyle が言ったことに続いて、マクロを使用して難しい作業を行うことができます。

可能です。

n 番目のビットを設定するには、OR を使用します。

x |= (1 << 5); // 右から 6 番目を設定します

少しクリアするには、AND を使用します。

x &= ~(1 << 5); // 右から 6 番目をクリアします

ビットを反転するには、XOR を使用します。

x ^= (1 << 5); // 右から 6 番目を反転

または...

#define GetBit(var, bit) ((var & (1 << bit)) != 0) // Returns true / false if bit is set
#define SetBit(var, bit) (var |= (1 << bit))
#define FlipBit(var, bit) (var ^= (1 << bit))

次に、次のようなコードで使用できます。

int myVar = 0;
SetBit(myVar, 5);
if (GetBit(myVar, 5))
{
  // Do something
}
于 2008-09-15T13:49:49.550 に答える
7

可能です。

n 番目のビットを設定するには、OR を使用します。

x |= (1 << 5); // sets the 5th-from right

少しクリアするには、AND を使用します。

x &= ~(1 << 5); // clears 5th-from-right

ビットを反転するには、XOR を使用します。

x ^= (1 << 5); // flips 5th-from-right

ビットの値を取得するには、シフトと AND を使用します。

(x & (1 << 5)) >> 5 // gets the value (0 or 1) of the 5th-from-right

注: 右にシフトする 5 は、値が 0 または 1 であることを確認するためのものです。

于 2008-09-15T13:13:24.007 に答える
3

この質問への答えを見てください。

于 2008-09-15T13:19:22.963 に答える
2

仮説

組み込みデータ型のn番目のビット(「char」など)にアクセスまたは設定するためのC構文はありません。ただし、論理AND演算を使用してビットにアクセスしたり、論理OR演算を使用してビットを設定したりできます。

例として、1101を保持する変数があり、左から2番目のビットをチェックするとします。0100で論理積を実行するだけです。

1101
0100
---- AND
0100

結果がゼロ以外の場合は、2番目のビットが設定されている必要があります。それ以外の場合は設定されていません。

左から3番目のビットを設定する場合は、0010と論理ORを実行します。

1101
0010
---- OR
1111

C演算子&&(ANDの場合)および||を使用できます (ORの場合)これらのタスクを実行します。ビットアクセスパターン(上記の例では0100と0010)を自分で作成する必要があります。秘訣は、最下位ビット(LSB)が1をカウントし、次のLSBが2をカウントし、次に4をカウントすることを覚えておくことです。したがって、n番目のLSB(0から開始)のビットアクセスパターンは単純に2^の値です。 n。これをCで計算する最も簡単な方法は、バイナリ値0001(この4ビットの例)を必要な桁数だけ左にシフトすることです。この値は、符号なし整数のような量では常に1に等しいため、これは「1<<n」にすぎません。

unsigned char myVal = 0x65; /* in hex; this is 01100101 in binary. */

/* Q: is the 3-rd least significant bit set (again, the LSB is the 0th bit)? */
unsigned char pattern = 1;
pattern <<= 3; /* Shift pattern left by three places.*/

if(myVal && (char)(1<<3)) {printf("Yes!\n");} /* Perform the test. */

/* Set the most significant bit. */
myVal |= (char)(1<<7);

この例はテストされていませんが、一般的な考え方を説明するのに役立つはずです。

于 2008-09-15T13:48:54.373 に答える
1

特定のインデックスを持つビットの状態を照会するには:

int index_state = variable & ( 1 << bit_index );

ビットを設定するには:

varabile |= 1 << bit_index;

ビットを再起動するには:

variable &= ~( 1 << bit_index );
于 2008-09-15T13:19:28.673 に答える
0

少しインデックスを付けたい場合は、次のことができます。

bit = (char & 0xF0) >> 7;

charのmsbを取得します。右シフトを省略して、0でテストを行うこともできます。

bit = char & 0xF0;

ビットが設定されている場合、結果は>0になります。

明らかに、異なるビットを取得するにはマスクを変更する必要があります(注:不明な場合は、0xFがビットマスクです)。多数のマスクを定義することが可能です。

#define BIT_0 0x1 // or 1 << 0
#define BIT_1 0x2 // or 1 << 1
#define BIT_2 0x4 // or 1 << 2
#define BIT_3 0x8 // or 1 << 3

等...

これはあなたに与えます:

bit = char & BIT_1;

上記のコードでこれらの定義を使用して、マクロまたは関数内のビットに正常にインデックスを付けることができます。

少し設定するには:

char |= BIT_2;

少しクリアするには:

char &= ~BIT_3

少し切り替えるには

char ^= BIT_4

この助け?

于 2008-09-15T13:15:57.743 に答える
0

ビットフィールドを使用してみてください。実装はコンパイラによって異なる可能性があることに注意してください。

http://publications.gbdirect.co.uk/c_book/chapter6/bitfields.html

于 2008-09-15T13:27:22.180 に答える
0

個々のビットは、次のようにインデックス付けできます。

次のような構造体を定義します。

struct
{
  unsigned bit0     : 1;
  unsigned bit1     : 1;
  unsigned bit2     : 1;
  unsigned bit3     : 1;
  unsigned reserved : 28;
} bitPattern;   

「value」という名前の変数の個々のビット値を知りたい場合は、次のようにします。

CopyMemory( &input, &value, sizeof(value) );

ビット 2 がハイかローかを確認するには:

int state = bitPattern.bit2;

お役に立てれば。

于 2008-09-15T13:55:21.533 に答える
0

ビット用の標準ライブラリ コンテナ std::vector があります。ライブラリに特化してスペース効率を高めています。ブーストの dynamic_bitset クラスもあります。

これらを使用すると、基になるストレージの値ごとに 1 ビットを使用して、ブール値のセットに対して操作を実行できます。

Boost ダイナミック ビットセットのドキュメント

STL ドキュメントについては、コンパイラのドキュメントを参照してください。

もちろん、他の整数型の個々のビットを手動でアドレス指定することもできます。これを行う場合は、上位ビットが設定された値で右シフトを行うことにした場合に未定義の動作が発生しないように、符号なしの型を使用する必要があります。ただし、コンテナーが必要なようです。

これが必要以上の 32 倍のスペースを必要とすることを主張したコメンターへ: boost::dynamic_bitset と vector はエントリごとに 1 ビットを使用するように特化されているため、実際にはプリミティブ型。これらのクラスを使用すると、効率的な基盤となるストレージを使用して、大きなコンテナー内の個々のビットに対処できます。(たとえば)32ビットが必要な場合は、必ずintを使用してください。大量のビットが必要な場合は、ライブラリ コンテナーを使用できます。

于 2008-09-15T13:25:45.770 に答える