質問

C++ 構造体がある場合、次のような 64 ビット データ ワードを定義します。

struct SMyDataWord
{
    int Name : 40;
    int Colour : 24;
};

は何ですか : 40 構文の意味...最初の 40 ビットは名前用に予約され、残りの 24 ビットは色用に予約されているという意味ですか?

このように使われているようですが、私はこれまで見たことがありません。

役に立ちましたか?

解決

Cから引き継がれた

ビットフィールド。 Name は40ビット幅、 Colour は24ビット幅です。したがって、構造体には少なくとも64ビットがあります。私のシステムでは、64ビットは8バイトになります。

他のヒント

これはビットフィールドの定義です。

Nameは、正確に40ビットの情報を保存できる整数です。カラーは24ビットを保存できます。

これは、頻繁に必要な構造のスペースを節約したり、CPUで処理しやすいサイズにコードを圧縮したりするためによく行われます(64ビットマシンの場合、Fitは正確に64ビットマシンのCPUレジスタに収まります)。

ビットフィールドにアクセスするコードの実行速度は少し遅くなります。

それらを慎重に使用する

  

ほとんどすべてのことを覚えておいてください   ビットフィールドは実装です   依存。たとえば、ビット   左から右に保存されるか、   右から左は実際の   ハードウェアアーキテクチャ。さらに、   各コンパイラは異なるメンバーを使用します   整列モデル、これがサイズの理由です   最適化されたBillingRecの12   9ではなくバイト。   ビットフィールドのアドレスも作成できません   ビットの配列。最後に、ほとんどの   ビットフィールドの使用の実装   速度のオーバーヘッドが発生します。したがって、   コードを最適化し、測定する   特定の最適化の効果と   使用する前のトレードオフ   それ。

ここ sizeof 内部で何が起こっているかをうまく示しています。

#include <iostream>
#include <climits>

struct bc_1 {
   int a : 1;
   int b : 1;
};

struct bc_2 {
   int a : 31;
   int b : 1;
};

struct bc_3 {
   int a : 32;
   int b : 1;
};

struct bc_4 {
   int a : 31;
   int b : 2;
};

struct bc_5 {
   int a : 32;
   int b : 32;
};

struct bc_6 {
   int a : 40;
   int b : 32;
};

struct bc_7 {
   int a : 63;
   int b : 1;
};

int main(int argc, char * argv[]) {
    std::cout << "CHAR_BIT = " << CHAR_BIT;
    std::cout << " => sizeof(int) = " << sizeof(int) << std::endl;

    std::cout << "1,  1:  " << sizeof(struct bc_1) << std::endl;
    std::cout << "31, 1:  " << sizeof(struct bc_2) << std::endl;
    std::cout << "32, 1:  " << sizeof(struct bc_3) << std::endl;
    std::cout << "31, 2:  " << sizeof(struct bc_4) << std::endl;
    std::cout << "32, 32: " << sizeof(struct bc_5) << std::endl;
    std::cout << "40, 32: " << sizeof(struct bc_6) << std::endl;
    std::cout << "63, 1:  " << sizeof(struct bc_7) << std::endl;
}

以下の内容は、コンパイラと OS、場合によってはハードウェアによって異なります。gcc-7 を使用した macOS 上 ( CHAR_BIT = 8、32 ビット int (すなわち、64ビットの半分 long) もっている sizeof(int) = 4) これは私が見た出力です:

CHAR_BIT = 8 => sizeof(int) = 4
1,  1:  4
31, 1:  4
32, 1:  8
31, 2:  8
32, 32: 8
40, 32: 12
63, 1:  8

これにより、いくつかのことがわかります。両方のフィールドの場合、 int 単一に収まるタイプ int (すなわち、上の例では 32 ビット)、コンパイラは 1 つのみを割り当てます。 intの記憶量 (bc_1 そして bc_2)。一度、シングル int ビットフィールドを保持できなくなったので、2 番目のビットフィールドを追加します (bc_3 そして bc_4)。ご了承ください bc_5 定員に達しています。

興味深いことに、許可されているよりも多くのビットを「選択」できます。見る bc_6. 。ここで g++-7 は警告を出します。

bitfields.cpp::30:13: warning: width of 'bc_6::a' exceeds its type
     int a : 40;
             ^~

ご了承ください:これについては、clang++ で詳しく説明しています。

bitfields.cpp:30:9: warning: width of bit-field 'a' (40 bits) exceeds the width of its type; value will be truncated to 32 bits [-Wbitfield-width]
    int a : 40;
    ^

ただし、内部ではコンパイラが別の割り当てを行っているようです。 intの価値のある思い出。少なくとも、正しいサイズが決定されます。コンパイラがこのメモリにアクセスしないよう警告しているのだと思います。 int a = bc_6::a (私はそう賭けます int a この場合、フィールドの最初の 32 ビットのみが含まれます。 bc_6::a...)。これは次によって確認されています bc_7 合計の大きさは2つです ints ですが、最初のフィールドでほとんどがカバーされます。

ついに交換 intlong 上記の例では、期待どおりに動作します。

CHAR_BIT = 8 => sizeof(long) = 8
1,  1:  8
31, 1:  8
32, 1:  8
31, 2:  8
32, 32: 8
40, 32: 16
63, 1:  8
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top