写嵌入式驱动时经常碰到这种情况:两个宏定义在不同文件里,必须保持一致,但没有任何机制强制它们匹配。
比如硬件驱动层定义了单次 DMA 的最大传输字节数,上层又计算了实际要传输的包大小——两个数字由不同参数决定,改一个忘了另一个,运行时才发现传输截断或花屏,而报错往往指向底层,很难找到根源。
一行代码可以解决:
_Static_assert(PACKET_MAX_SIZE <= DMA_MAX_TRANSFER_BYTES,
"Packet size exceeds DMA limit");
放在宏定义之后、任何函数之前。只要有人改了相关配置导致不一致,编译直接失败:
error: static assertion failed: "Packet size exceeds DMA limit"
不用烧板子,不用跑代码,问题在编译期暴露。
基本语法
_Static_assert(常量表达式, "错误信息");
条件必须是编译期可求值的常量表达式,这是最重要的限制:
// ✅ 可以——编译期已知
_Static_assert(sizeof(packet_t) == 12, "Header size mismatch");
_Static_assert(BUF_SIZE % 4 == 0, "Must be 4-byte aligned");
_Static_assert(MODE_COUNT <= MAX_MODES, "Too many modes");
// ❌ 不行——运行时才知道值
int n = get_count();
_Static_assert(n < MAX, "..."); // 编译报错
标准与兼容性
- C11 起内置关键字,无需任何头文件,GCC / Clang / MSVC 均支持
- C++ 里等价写法是
static_assert(不带下划线) <assert.h>中的static_assert宏只是_Static_assert的别名,用于 C/C++ 共用代码- C99 及更早不支持,可用以下 trick 模拟:
// 利用负数数组长度会触发编译错误的特性
#define STATIC_ASSERT(cond) typedef char static_assert_[(cond) ? 1 : -1]
报错信息没有 _Static_assert 友好,但原理相同。
还能用在哪
// 结构体尺寸符合协议定义
_Static_assert(sizeof(packet_header_t) == 12, "Header size mismatch");
// 枚举数量不超出数组边界
_Static_assert(MODE_COUNT <= MAX_MODES, "Too many modes defined");
// 缓冲区满足对齐要求
_Static_assert(sizeof(dma_buf_t) % 4 == 0, "DMA buffer must be 4-byte aligned");
// 配置参数在合法范围内
_Static_assert(TASK_STACK_SIZE >= 2048, "Stack too small");
对比
| 方式 | 发现时机 | 运行时开销 |
|---|---|---|
| 不检查 | 花屏/崩溃后靠经验定位 | 无 |
| 运行时 assert | 执行到那行才触发 | 有 |
_Static_assert |
编译时,0 开销 | 无 |
凡是”两个地方的数字必须匹配”的场景,都值得加一个。改配置时编译器帮你兜底。

![表情[qiang]-逻辑矩阵技术社区](https://szlogicmatrix.com/wp-content/themes/zibll/img/smilies/qiang.gif)
