ビットフィールドを構造体で表現
構造体でビットフィールドを管理できます。
例えば、下記は、1ビット単位で4つのフィールドを定義しました。
typedef struct{
unsigned int B0 : 1;
unsigned int B1 : 1;
unsigned int B2 : 1;
unsigned int B3 : 1;
} Reg_t;
共用体で、下記のように定義することで、ビットフィールドで定義した値を、unsigned intの単位で参照できます。
typedef union{
Reg_t regBit;
unsigned int reg;
}RegUnion_t;
例えば、下記のようにビットフィールド単位で値を代入して、
regUnion.reg = 0; regUnion.regBit.B3 = 1; regUnion.regBit.B2 = 1; regUnion.regBit.B1 = 0; regUnion.regBit.B0 = 1;
unsigned intの単位で参照します。これが共用体の効果ですね。
printf("reg=%d\n", regUnion.reg);
サンプルコード
下記がサンプルコードになります。
$ cat sample.c
#include <stdio.h>
typedef struct{
unsigned int B0 : 1;
unsigned int B1 : 1;
unsigned int B2 : 1;
unsigned int B3 : 1;
} Reg_t;
typedef union{
Reg_t regBit;
unsigned int reg;
}RegUnion_t;
int main(){
RegUnion_t regUnion;
regUnion.reg = 0;
regUnion.regBit.B3 = 1;
regUnion.regBit.B2 = 1;
//regUnion.regBit.B1 = 3;
regUnion.regBit.B1 = 0;
regUnion.regBit.B0 = 1;
printf("size=%lu\n", sizeof(regUnion.regBit));
printf("B3=%d \nB2=%d \nB1=%d \nB0=%d\n", regUnion.regBit.B3, regUnion.regBit.B2, regUnion.regBit.B1, regUnion.regBit.B0);
printf("reg=%d\n", regUnion.reg);
return 0;
}
下記が実行結果になります。
$ gcc -o sample sample.c $ ./sample size=4 B3=1 B2=1 B1=0 B0=1 reg=13
スポンサーリンク
warning: implicit truncation from 'int' to bit-field changes value from 2 to 0
定義したビットフィールドのビット幅を超えて、値を代入すると、
warningがでます。
例えば、ビット幅を1で定義しているところに、
typedef struct{
〜省略〜
unsigned int B3 : 1;
} Reg_t;
ビット幅1を超えて、値を代入すると、
regUnion.regBit.B1 = 3;
下記のような、warningがでます。
$ gcc -o sample sample.c
sample.c:21:21: warning: implicit truncation from 'int' to bit-field changes value from 3 to 1
[-Wbitfield-constant-conversion]
regUnion.regBit.B1 = 3;
^ ~
1 warning generated.
メモリサイズとアライメント
ビットフィールドで定義された構造体のメモリサイズは、アライメントされてメモリサイズとなります。
例えば、下記の場合は4バイトのint型なので、下記のように31ビットで定義しても、メモリサイズは4バイトになります。
typedef struct{
unsigned int B0 : 1;
unsigned int B1 : 2;
unsigned int B2 : 3;
unsigned int B3 : 25;
} Reg_t;
下記のように、33ビットとすると、4バイトアライメントなので、メモリサイズは8バイトになりますね。
typedef struct{
unsigned int B0 : 1;
unsigned int B1 : 2;
unsigned int B2 : 3;
unsigned int B3 : 27;
} Reg_t;
