嵌入式 C 语言结构体实战指南:定义、用法与内存优化
结构体是高效嵌入式 C 编程的基石。本文探讨其实际应用、声明语法及数据对齐对内存占用的影响。通过策略性排序结构体成员,往往能缩减数据对象体积,这在资源受限环境至关重要。
本文提供嵌入式 C 结构体简明而全面的概览。涵盖实际应用、正确声明方法、影响结构体大小的微妙数据对齐规则。
结构体
当多个同类型变量有逻辑关联,数组是便捷分组。例如保存 ADC 数字化语音输入的最近 50 个采样:
uint16_t voice[50];
uint16_t 是 stdint.h 定义的无符号 16 位整数,确保跨平台尺寸一致。
但若需分组不同类型变量——如采样数组和 ADC 采样率?分别声明为独立变量产生不必要开销。可封装进结构体:
struct record { uint16_t voice[50]; float sample_rate; };
record 结构体现包含 uint16_t 数组和 float 于单一逻辑关联的数据对象。
结构体为何重要?
结构体让你将异构变量关联成内聚单元,简化操作、增强可读性。它们是更复杂数据结构(链表、消息缓冲区)基础,嵌入式通信和传感器数据处理中无处不在。
例如,微控制器内存映射外设常用镜像硬件寄存器布局的结构体表示,允许通过成员语法直接访问寄存器。

图 1. 结构体可用于实现链表。

图 2. STM32 MCU 内存映射。图片来源:Embedded Systems with ARM。
声明结构体
首先定义结构体模板。示例:
struct record { uint16_t voice[4]; float sample_rate; };
模板本身不占内存;仅声明该类型变量时分配:
struct record mic1;
现在 mic1 占四个 uint16_t 元素和一个 float 空间。通过点运算符访问成员:
mic1.voice[0] = 100; float fs = mic1.sample_rate;
结构体的其他声明方式
虽最常见模式是先定义结构体再声明变量,C 语言提供替代语法:
语法 1:标签与变量合并
struct record { uint16_t voice[4]; float sample_rate; } mic1;
后续变量可单独声明:
struct record mic2;
语法 2:匿名模板
struct { uint16_t voice[4]; float sample_rate; } mic1;
无名称无法在别处复用模板。
语法 3:匿名嵌套结构体
struct test { struct { float f; char a; }; } test_var;
直接访问内部成员:
test_var.f = 1.2f;
匿名结构体减少冗余但审慎使用以保清晰度。
结构体内存布局
C 标准保证成员按声明顺序在内存中顺序排列。例如:
struct Test2 { uint8_t c; uint32_t d; uint8_t e; uint16_t f; } MyStruct;
32 位机上,sizeof(MyStruct) 为 12 字节,因填充对齐 uint32_t 到 4 字节边界。重排成员可消除填充:
struct Test2 { uint32_t d; uint16_t f; uint8_t c; uint8_t e; } MyStruct;
现在 sizeof(MyStruct) 降至 8 字节——内存受限固件的宝贵节省。

图 3. 数据对齐可给结构体内存布局增加填充。
总结
- 结构体将异构变量打包成单一可管理单元,提升代码清晰度和效率。
- 自定义数据结构支持设备间消息传递和传感器数据存储等任务。
- 它们是内存映射外设硬件寄存器映射的关键。
- 重排成员遵循对齐规则可显著缩减结构体大小。
探索更多嵌入式 C 教程 点此。
嵌入式