導入
C 言語では、联合体
(union) と结构体
(struct) は、データのさまざまな表現を処理するために使用できる 2 つの強力なデータ型です。この記事では、共用体と構造体を使用してビット フィールド、特に 16 ビットおよび 32 ビットの符号なし整数を管理する方法について説明します。
連合
ユニオンは、異なるデータ型を同じメモリ位置に格納できるようにする特別なデータ構造です。これは、共用体のすべてのメンバーが同じメモリ空間を共有することを意味します。この例では、UNIO_U16
という共用体を定義します。これには、16 ビット符号なし整数を格納するためのメンバーData_u16
と、ビットごとのアクセスのための構造体メンバーが含まれていますBits
。構造体 Bits は、16 ビット整数の各ビットを表す 16 ビット フィールドを定義します。
typedef union
{
uint16_t Data_u16;
struct
{
uint16_t Bit0: 1;
uint16_t Bit1: 1;
// ...
uint16_t Bit14: 1;
uint16_t Bit15: 1;
} Bits;
} UNIO_U16;
構造体 (構造体)
構造体は、異なるデータ型の複数の変数をカスタム データ型に結合する方法です。この例では、UNIO_U32
という共用体を定義します。これには、32 ビット符号なし整数を格納するためのメンバーData_u32
と、ビットごとのアクセスのための構造体メンバー Bits が含まれています。構造体 Bits は、32 ビット整数の各ビットを表す 32 ビット フィールドを定義します。
typedef union
{
uint32_t Data_u32;
struct
{
uint32_t Bit0: 1;
uint32_t Bit1: 1;
// ...
uint32_t Bit30: 1;
uint32_t Bit31: 1;
} Bits;
} UNIO_U32;
共用体と構造体の使用例
共用体と構造体を使用すると、整数のさまざまなビットに簡単にアクセスできます。たとえば、16 ビット整数のビット 0 と 5 は次のコードで設定できます。
UNIO_U16 u16;
u16.Bits.Bit0 = 1;
u16.Bits.Bit5 = 1;
printf("u16.Data_u16 = %u\n", u16.Data_u16);
同様に、32 ビット整数のビット 0 と 10 を設定することもできます。
UNIO_U32 u32;
u32.Bits.Bit0 = 1;
u32.Bits.Bit10 = 1;
printf("u32.Data_u32 = %u\n", u32.Data_u32);
よく使用されるUNIO_U8、UNIO_U16、UNIO_U32のリファレンスサンプルコードを定義する
#include <stdio.h>
#if defined(__GNUC__) // GCC编译器
#if __x86_64__ || __ppc64__ || __aarch64__ || __mips64 || _M_X64 // 64位编译器判断
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
#else // 32位编译器
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned long uint32_t;
#endif
#elif defined(_MSC_VER) // Microsoft Visual C++编译器
#if defined(_WIN64) // 64位编译器判断
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
#else // 32位编译器
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned long uint32_t;
#endif
#else
#error "Unsupported compiler. Please add compiler-specific checks."
#endif
typedef union
{
uint16_t Data_u16;
struct
{
uint8_t LowByte;
uint8_t HighByte;
} Bytes;
struct
{
uint16_t Bit0: 1;
uint16_t Bit1: 1;
uint16_t Bit2: 1;
uint16_t Bit3: 1;
uint16_t Bit4: 1;
uint16_t Bit5: 1;
uint16_t Bit6: 1;
uint16_t Bit7: 1;
uint16_t Bit8: 1;
uint16_t Bit9: 1;
uint16_t Bit10: 1;
uint16_t Bit11: 1;
uint16_t Bit12: 1;
uint16_t Bit13: 1;
uint16_t Bit14: 1;
uint16_t Bit15: 1;
} Bits;
} UNIO_U16;
typedef union
{
uint32_t Data_u32;
struct
{
uint16_t LowWord;
uint16_t HighWord;
} Words;
struct
{
uint8_t Byte0;
uint8_t Byte1;
uint8_t Byte2;
uint8_t Byte3;
} Bytes;
struct
{
uint16_t Bit0: 1;
uint16_t Bit1: 1;
uint16_t Bit2: 1;
uint16_t Bit3: 1;
uint16_t Bit4: 1;
uint16_t Bit5: 1;
uint16_t Bit6: 1;
uint16_t Bit7: 1;
uint16_t Bit8: 1;
uint16_t Bit9: 1;
uint16_t Bit10: 1;
uint16_t Bit11: 1;
uint16_t Bit12: 1;
uint16_t Bit13: 1;
uint16_t Bit14: 1;
uint16_t Bit15: 1;
uint16_t Bit16: 1;
uint16_t Bit17: 1;
uint16_t Bit18: 1;
uint16_t Bit19: 1;
uint16_t Bit20: 1;
uint16_t Bit21: 1;
uint16_t Bit22: 1;
uint16_t Bit23: 1;
uint16_t Bit24: 1;
uint16_t Bit25: 1;
uint16_t Bit26: 1;
uint16_t Bit27: 1;
uint16_t Bit28: 1;
uint16_t Bit29: 1;
uint16_t Bit30: 1;
uint16_t Bit31: 1;
} Bits;
} UNIO_U32;
int main()
{
UNIO_U16 u16;
u16.Bits.Bit0 = 1;
u16.Bits.Bit5 = 1;
printf("u16.Data_u16 = %u\n", u16.Data_u16);
UNIO_U32 u32;
u32.Bits.Bit0 = 1;
u32.Bits.Bit10 = 1;
printf("u32.Data_u32 = %u\n", u32.Data_u32);
return 0;
}
在上述代码中,我们定义了 UNIO_U16 和 UNIO_U32 两个联合体,每个联合体包含一个用于存储整数的成员(Data_u16 和 Data_u32) 以及一个用于按位访问的 Bits 结构体成员。可以根据需要设置每个位的值,并使用 printf 输出整数值。 注意在联合体中,各个成员共享同一段内存空间,因此根据对不同成员的赋值,联合体中存储的整数值也会发生相应的变化。
結論は
ユニオンと構造体は、C でデータを操作するための強力なツールです。ユニオンを使用してさまざまなタイプのデータを格納し、構造体を使用してビットフィールドを管理することで、データをより柔軟かつ効率的に操作できます。この手法は、組み込みシステムやハードウェア関連のプログラミング タスクを扱う場合に特に役立ちます。