スポンサーリンク

ビットフィールドを構造体で表現

構造体でビットフィールドを管理できます。
例えば、下記は、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;

スポンサーリンク