4

まず、問題のアプリケーションは常に同じプロセッサ上にあり、コンパイラは常に gcc であるため、ビットフィールドが移植可能でないことは心配していません。

gcc は、最初にリストされたフィールドがバイトの最下位ビットに対応するようにビットフィールドをレイアウトします。したがって、a =0、b =1、c =1、d =1 の次の構造ではe0バイトられます。

struct Bits {
  unsigned int a:5;
  unsigned int b:1;
  unsigned int c:1;
  unsigned int d:1;
} __attribute__((__packed__));

(実はこれは C++ なので、g++ のことを言っています。)

ここで、 aを 6 ビット整数にしたいとします。

これで、なぜこれが機能しないのかがわかりますが、次の構造をコーディングしました。

struct Bits2 {
  unsigned int a:6;
  unsigned int b:1;
  unsigned int c:1;
  unsigned int d:1;
} __attribute__((__packed__));

bc、およびdを 1 に設定し、 aを 0 に設定すると、次の 2 バイトになります。

c0 01

これは私が欲しかったものではありません。私はこれを見たいと思っていました:

e0 00

最初のバイトの最上位ビットに 3 ビット、最初のバイトの最下位 5 ビットと 2 番目の最上位ビットにまたがる 6 ビットを持つ構造を指定する方法はありますか?

これらのビットがどこに配置されるかは、私には制御できないことに注意してください。これは、他の誰かのインターフェイスによって定義されたビットのレイアウトです。

4

3 に答える 3

3

通常、ユニオンがどのようにパックされるかについて強い仮定を行うことはできません。すべてのコンパイラの実装は、異なる方法でパックすることを選択する場合があります (スペースを節約するため、またはバイト内のビットフィールドを整列させるため)。

マスキングとビットごとの演算子を使用することをお勧めします..

このリンクから:

ビットフィールドの主な用途は、データを密にパッキングできるようにするか、外部で生成されたデータ ファイル内のフィールドを指定できるようにすることです。C は機械語内のフィールドの順序を保証しないため、後者の理由でそれらを使用すると、プログラムは移植性がなくなるだけでなく、コンパイラにも依存します。標準では、フィールドは通常は機械語である「ストレージ ユニット」にパックされると記載されています。パッキングの順序、およびビットフィールドがストレージ ユニットの境界を超えるかどうかは、実装によって定義されます。ストレージ ユニット境界への整列を強制するには、整列させたいフィールドの前にゼロ幅フィールドが使用されます。

于 2010-04-19T01:41:37.033 に答える
3

(これはすべてgcc固有の解説であることに注意してください-ビットフィールドのレイアウトが実装定義であることはよく知っています)。

リトル エンディアン マシンではありません: 問題は、リトル エンディアン マシンでは、2 番目のバイトの最上位ビットが最初のバイトの最下位ビットに「隣接」していると見なされないことです。

ただし、ビットフィールドをntohs()関数と組み合わせることができます。

union u_Bits2{
    struct Bits2 {
      uint16_t _padding:7;
      uint16_t a:6;
      uint16_t b:1;
      uint16_t c:1;
      uint16_t d:1;
    } bits __attribute__((__packed__));
    uint16_t word;
}

union u_Bits2 flags;
flags.word = ntohs(flag_bytes_from_network);

ただし、ビットフィールドを避け、代わりにシフトとマスクを使用することを強くお勧めします。

于 2010-04-19T02:25:57.160 に答える
0

<stdint.h>C/C++ には、構造体のビットごとのメモリ レイアウトを指定する手段がないため、8 ビットまたは 16 ビット (符号なし) 整数 (またはからの uint8_t、uint16_t) で手動のビット シフトとマスキングを行う必要があります<cstdint>

私が知っている十数個のプログラミング言語のうち、ビット フィールドのビットごとのメモリ レイアウトを指定できる言語はごくわずかです: Ada、Erlang、VHDL (および Verilog)。

(そのリストにさらに言語を追加したい場合は、コミュニティ wiki を参照してください。)

于 2010-04-19T02:03:32.057 に答える