位域与联合体
2026/7/7大约 2 分钟
位域与联合体
一、位域
位域用 : 指定成员占用的 bit 数:
struct {
uint16_t len : 15;
uint16_t finish : 1;
} sta;
16 bit
┌───────────────────────────────┬───┐
│ len │fin│
│ 15 bit │1bit
└───────────────────────────────┴───┘len:15 bit,范围0 ~ 32767finish:1 bit,通常为0/1- 位域位序、存储布局、对齐方式属于实现相关
二、位域的作用
传统方式:
#define TX_ENABLE_BIT (1U << 0)
#define RX_ENABLE_BIT (1U << 1)
#define PARITY_MASK (0x3U << 2)
reg |= TX_ENABLE_BIT;
reg |= RX_ENABLE_BIT;
reg = (reg & ~PARITY_MASK) | (2U << 2);位域:
reg.bits.tx_enable = 1;
reg.bits.rx_enable = 1;
reg.bits.parity = 2;核心:
用字段的方式操作 bit。
硬件寄存器中要注意位域布局依赖编译器/ABI。
三、联合体
union 的所有成员共享同一块内存。
typedef union
{
uint16_t reg;
struct
{
uint16_t pin_mode : 2;
uint16_t pin_speed : 2;
uint16_t pull_updown : 2;
uint16_t output_type : 1;
uint16_t reserved : 9;
} bit;
} GPIO_CONFIG_Reg;
GPIO_CONFIG.reg = 0x1234; // 整体访问
GPIO_CONFIG.bit.pin_mode = 1; // 字段访问核心:
union:同一块内存,用不同成员解释。
四、位域 + 联合体
同一块数据
├── reg:整体访问
└── bit:按字段访问常用于:
- 寄存器字段
- 状态标志
- 协议字段
五、映射硬件寄存器
#define GPIOA_CONFIG \
(*(volatile GPIO_CONFIG_Reg *)0x40020000)
GPIOA_CONFIG.reg = 0;
GPIOA_CONFIG.bit.pin_mode = 1;六、基本类型大小
| 类型 | STM32 常见 32 位 ARM | Linux x86-64 常见 |
|---|---|---|
char | 1 字节 | 1 字节 |
short | 2 字节 | 2 字节 |
int | 4 字节 | 4 字节 |
long | 4 字节 | 8 字节 |
long long | 8 字节 | 8 字节 |
long大小由平台/ABI决定。
七、位域结构体 struct A
struct A
{
char t : 4;
char k : 4;
unsigned short i : 8;
unsigned long m;
};注意:
t:4 + k:4 = 8 bit = 1 字节在 STM32 常见 32 位 ARM GCC 环境下,典型布局:
t+k 1 字节
i 2 字节
padding 1 字节
m 4 字节
----------------
sizeof 8 字节
sizeof(struct A) == 8但位域布局和 long 大小都与平台有关。
八、结构体中出现 union
struct A
{
char a;
union
{
int i;
char buf[4];
} u;
char b;
};假设:
char = 1
int = 4则:
union u:
最大成员 = 4 字节
对齐要求 = 4 字节结构体通常:
a 1
padding 3
u 4
b 1
tail padding 3
----------------
sizeof 12核心:
union 内部成员共享空间,不累加;union 作为结构体成员时,仍然参与结构体对齐。
九、最终记忆
位域 → 按 bit 划分字段
union → 成员共享内存
struct → 成员按各自对齐要求排列
padding → 为满足对齐而增加的空间算结构体大小:看成员布局 → 看对齐 → 加 padding → 最后满足整体对齐。

