Skip to main content

IAR Embedded Workbench for Arm 9.70.x

ビットフィールド

このセクションの内容:

標準のCでは、intsigned intunsignedintを整数ビットフィールドの基本型として使用できます。標準のC++およびCでは、コンパイラで言語拡張が有効になっている場合、任意の整数または列挙型を基本型として使用できます。単純な整数型(charshortintなど)が符号つきまたは符号なしのビットフィールドになるかどうかは、実装によって定義されます。

IAR C/C++ コンパイラfor Armでは、単純な整数型は符号なしとして処理されます。

式のビットフィールドは、intがビットフィールドのすべての値を表せる場合、intとして扱われます。それ以外の場合は、ビットフィールドの基本型として処理されます。

各ビットフィールドは、ビットフィールドを格納するために使用可能なビットを十分に持つ基本型の次の適切に整列されたコンテナに配置されます。それぞれのコンテナの中では、バイトオーダを考慮して、最初に使用可能なバイト内にビットフィールドが配置されます。必要があればコンテナはタイプで適切に整列される限りは、重ねられることに注意してください。

また、異なる型のビットフィールドコンテナが重複できない場合、コンパイラは代替のビットフィールド割当て方式(分割された型)に対応します。この割当て方式を使用すると、各ビットフィールドは型が前のビットフィールドのものと異なったり、前のビットフィールドと同じコンテナにビットフィールドが合わない場合、新しいコンテナに配置されます。各コンテナ内では、ビットフィールドは最下位のビットから最上位ビット(分割された型)へ、あるいは最上位ビットから最下位ビット(逆順の分割された型)へと配置されます。この割当て方式では、デフォルトの割当て方式(連結された型)より使用スペースが少なくなることは決してなく、ビットフィールドの型が混在する場合は格段に多くのスペースを使用することがあります。

#pragma bitfields ディレクティブを使用して、ビットフィールドの割当て方式を選択してください(bitfieldsを参照)。

次の例を考えてみます。

struct BitfieldExample
{
  uint32_t a : 12;
  uint16_t b : 3;
  uint16_t c : 7;
  uint8_t  d;
};
連結された型のビットフィールド割当て方式の例

最初のビットフィールドaを配置するために、コンパイラは32ビットのコンテナをオフセット0に割当て、aをコンテナの最初のバイトと2番目のバイトに入れます。

2番目のビットフィールドbについては、16ビットのコンテナが必要です。オフセット0に4つの空いているビットがまだあるため、ビットフィールドはそこに配置されます。

3番目のビットフィールドcは、最初の16ビットコンテナに1ビットしか残っていないため、オフセット2に新しいコンテナが割り当てられ、cはこのコンテナの最初のバイトに入れられます。

4番目のメンバであるdは、次に使用可能なフルバイト、つまりオフセット3のバイトに配置できます。,

リトルエンディアンモードでは、各ビットフィールドは左から右の順にバイトに配置されるように、コンテナの最下位の空いているビットから割り当てられます。

LayoutBitfieldJoinedLEmode_100percent.png

ビッグエンディアンモードでは、各ビットフィールドは左から右の順にバイトに配置されるように、コンテナの最上位の空いているビットから割り当てられます。

LayoutBitfieldJoinedBEmode_100percent.png
分割された型のビットフィールド割当て方式の例

最初のビットフィールドaを配置するために、コンパイラは32ビットのコンテナをオフセット0に割当て、aを最も重要でない12ビットのコンテナに入れます。

2番目のビットフィールドbを配置するために、新しいコンテナがオフセット4に割当てられます。これは、ビットフィールドの型が前のビットフィールドと同じではないためです。bは、このコンテナの最下位の3ビットに配置されます。

3番目のビットフィールドcbと同じ型なので、同じコンテナに入ります。

4番目のメンバdは、オフセット6のバイトに割り当てられます。dは、bcと同じコンテナには配置できません。その理由は、これがビットフィールドではなく、同じ型でもないために、合わないからです。

逆順(逆順の分割された型)を使用する際は、各ビットフィールドはそのコンテナの最上位ビットから配置されます。

これは、リトルエンディアンモードのbitfield_exampleのレイアウトです。

LayoutBitfieldDisjointLittleEmode 100percent.png

これは、ビッグエンディアンモードのbitfield_exampleのレイアウトです。

LayoutBitfieldDisjointBigEmode 100percent.png
パディング

ビットフィールドにアクセスするときに上記のように表示されるように、ビットフィールドコンテナ全体を読み取る/書き込むために、パディングは通常構造の終わりに追加されます。ただし、ビットが低から高のアドレスに割り当てられているときは、フィールドのアライメントを行う必要がある場合のみパディングは追加されます。

例:

struct X { uint32_t x1 : 5; };

uint32_tビットフィールドのアライメントが4のとき、struct Xのサイズは4で、通常のアライメントでビットフィールドコンテナ (uint32_t) 全体を読み取り/書き込むことができます。ただし、フィールドのアライメントが低く(例えば、#pragma packを使用していることで)、ビットが低アドレスに割り当てられている場合、struct Xのサイズも小さいです。