1

uint16_t特定のビットを設定する必要がある変数があるとします。

例:

uint16_t field = 0;

これは、ビットがすべてゼロであることを意味します。0000 0000 0000 0000

これで、特定の位置に設定する必要があるいくつかの値を取得できました。

val1=1; val2=2, val3=0, val4=4, val5=0;

ビットを設定する構造は次のとおりです。

0|000|  0000| 0000 000|0

val1左側の最初のビットに設定する必要があります。そのため、1つまたは0のみです。

val2次の 3 ビットで設定する必要があります。val3次の 4 ビットで。val4次の 7 ビットとval51 つの最後のビット。

結果は次のようになります。 1010 0000 0000 1000

「グループ」ではなく、特定のビットの方法しかわかりませんでした。(シフトまたはビットセット)

この問題を解決する方法を知っている人はいますか?

4

5 に答える 5

8

(少なくとも) 2 つの基本的なアプローチがあります。1 つは、いくつかのビットフィールドを持つ構造体を作成することです。

struct bits { 
    unsigned a : 1;
    unsigned b : 7;
    unsigned c : 4;
    unsigned d : 3;
    unsigned e : 1;
};

bits b;

b.a = val1;
b.b = val2;
b.c = val3;
b.d = val4;
b.e = val5;

16 ビット値を取得するには、(一例として) その構造体とuint16_t. ちょっとした問題が 1 つだけあります。標準では、16 ビット値を見たときにビット フィールドが最終的にどのような順序になるかは保証されていません。たとえば、上で示した順序を逆にして、本当に必要な最上位ビットから最下位ビットへの順序を取得する必要がある場合があります (ただし、コンパイラを変更すると、再び混乱する可能性があります)。

もう 1 つの明白な可能性は、シフトとマスキングを使用して、ピースをまとめて数字にすることです。

int16_t result = val1 | (val2 << 1) | (val3 << 8) | (val4 << 12) | (val5 << 15);

今のところ、各入力は正しい範囲で始まる (つまり、選択したビット数で表現できる値を持つ) と想定しています。間違っている可能性がある場合は、最初に正しいビット数にマスクする必要があります。これを行う通常の方法は、次のようなものです。

uint16_t result = input & ((1 << num_bits) - 1);

そこの数学に興味がある場合は、次のように機能します。入力が 4 ビットに収まるようにしたいとします。1左に 4 ビットシフトする00010000と (バイナリで) 生成されます。それから 1 を引くと、設定されている 1 ビットがクリアされ、それより下位のすべてのビットが設定さ00001111れます。これにより、最初の最下位ビット セットが得られます。それと入力の間でビットごとに行うANDと、入力に設定された上位ビットは結果でクリアされます。

于 2013-06-27T06:10:17.843 に答える
1

解決策の 1 つは、次のように N 番目のビットから始まる K ビットの値を設定することですfield

uint16_t value_mask = ((1<<K)-1) << N; // for K=4 and N=3 will be 00..01111000
field = field & ~value_mask; // zeroing according bits inside the field
field = field | ((value << N) & value_mask); // AND with value_mask is for extra safety

または、uint16_t の代わりに struct を使用できる場合は、ビット フィールドを使用して、コンパイラにこれらすべてのアクションを実行させることができます。

于 2013-06-27T06:08:26.247 に答える
0

このコードを試してください:

uint16_t shift(uint16_t num, int shift)
{
    return num | (int)pow (2, shift);
}

シフトは、設定したいビットの位置です

于 2013-06-27T06:13:23.567 に答える
0
finalvle = 0;
finalvle = (val1&0x01)<<15;
finalvle += (val2&0x07)<<12;
finalvle += (val3&0x0f)<<8
finalvle += (val4&0xfe)<<1;
finalvle += (val5&0x01);
于 2013-06-27T06:08:22.513 に答える
0

これを実現するには、ビットごとの or およびシフト演算子を使用できます。

shift<<を使用して「バイトを左に移動」します。

int i = 1;  // ...0001
int j = i << 3 // ...1000

次に、ビットごとに使用するか|、適切な場所に配置できます(上書きしようとしているビットにすべてゼロがあると仮定します)。

int k = 0;  // ...0000
k |= i // ...0001
k |= j // ...1001

編集:@Inspiredの回答では、特定のビット領域をゼロにすることも説明されていることに注意してください。それを適切に実装する方法を全体的に説明します。

于 2013-06-27T06:09:37.017 に答える