web-dev-qa-db-ja.com

1バイト内に8つの論理true / false値を格納しますか?

私は2KBのSRAMしか持たないマイクロコントローラーに取り組んでおり、必然的にメモリを節約する必要があります。私は8を置くことができる方法を考え出そうとしています0/1値をビットフィールドを使用して1バイトに変換しますが、うまく処理できません。

struct Bits
{
    int8_t b0:1, b1:1, b2:1, b3:1, b4:1, b5:1, b6:1, b7:1;
};

int main(){
    Bits b;
    b.b0 = 0;
    b.b1 = 1;

    cout << (int)b.b0; // outputs 0, correct
    cout << (int)b.b1; // outputs -1, should be outputting 1
}

何ができますか?

64
Jazcash

すべてのビットフィールドメンバーは、符号付き1ビット整数です。 2の補数システムでは、これらはどちらか一方のみを表すことができることを意味します0または-1。使用する uint8_t お望みならば 0および1

struct Bits
{
    uint8_t b0:1, b1:1, b2:1, b3:1, b4:1, b5:1, b6:1, b7:1;
};
112
Carl Norum

注意として-この規格はビットフィールドの実装スキームを実際に強制するものではありません。 Bitsが1バイトになる保証はなく、仮想的にそれが大きくなることは完全に可能です。

しかし実際には、実際の実装は通常、明白なロジックに従い、「ほぼ常に」サイズが1バイトになりますが、これが保証されている必要はありません。念のため、念のため 手動で行う を使用してください。

ところで-1はまだtrueですが、-1 != true

13
dtech

前述のように、これらの変数は符号ビットのみで構成されているため、使用可能な値は_0_および_-1_のみです。

これらのビットフィールドのより適切なタイプはboolです。 C++ 14§9.6/ 4:

trueまたはfalseが任意のサイズ(1ビットのビットフィールドを含む)のbool型のビットフィールドに格納されている場合、元のbool値とビットフィールドの値は等しいと比較します。

はい、_std::uint8_t_で十分ですが、最適な方法を使用することもできます。 std::cout << (int)b.b0;のキャストのようなものは必要ありません。

3
Potatoswatter

符号付き整数と符号なし整数が答えです。

シグナリングは単なるビットの解釈であり、-1または1は「変数型」を解釈する「印刷」シリアライザにすぎないことに注意してください。コンパイラによって関数(演算子のオーバーロードを調べる)が「明らかにされた」ため、ビットは同じ、その値も(オン/オフ)-1ビットしかないため。

気にしないでくださいが、明示的にすることをお勧めします。符号なしで変数を宣言することをお勧めします。これにより、「print」のようなシリアライザに値を設定または取得するときに適切なコードをマウントするようコンパイラに指示します)。

"COUT"演算子のオーバーロード: "cout"は、パラメーターのオーバーロードが呼び出す関数をコンパイラーに指示する一連の関数を通じて機能します。したがって、2つの関数があり、1つは符号なしを受け取り、もう1つは符号付きを受け取るため、同じデータを異なる方法で解釈することができ、それを変更して、キャストを使用して別の関数を呼び出すようにコンパイラーに指示できます。 cout << myclass を参照

0
Luciano