静态断言
静态断言在编译时检查条件,如果条件为假则产生编译错误。C11 引入 _Static_assert(C11 关键字)和 static_assert 宏(在 <assert.h> 中)。静态断言是确保编译期常量、类型大小、配置正确性的有力工具。
C11 _Static_assert
_Static_assert(sizeof(int) == 4, "int must be 4 bytes");
_Static_assert(CHAR_BIT == 8, "char must be 8 bits");
/* 在结构体定义中 */
struct Packet {
uint32_t header;
uint8_t data[100];
};
_Static_assert(sizeof(struct Packet) == 104, "Packet size mismatch");
static_assert 宏
#include <assert.h>
static_assert(sizeof(int) == 4, "int must be 4 bytes");
C99 模拟静态断言
/* C99 技巧:利用 typedef 和负大小数组 */
#define STATIC_ASSERT(expr) \
typedef char _static_assert_##__LINE__[(expr) ? 1 : -1]
STATIC_ASSERT(sizeof(int) == 4);
STATIC_ASSERT(CHAR_BIT == 8);
如果条件为假,编译器报错:error: size of array '_static_assert_123' is negative
使用场景
类型大小检查:
#include <stdint.h>
static_assert(sizeof(int32_t) == 4, "int32_t must be 4 bytes");
static_assert(sizeof(int64_t) == 8, "int64_t must be 8 bytes");
结构体布局:
struct Header {
uint16_t magic;
uint32_t size;
uint16_t flags;
};
static_assert(sizeof(struct Header) == 8, "Header must be packed");
static_assert(offsetof(struct Header, size) == 2, "size offset");
配置检查:
#define BUFFER_SIZE 1024
static_assert(BUFFER_SIZE >= 256, "Buffer too small");
static_assert(BUFFER_SIZE <= 65536, "Buffer too large");
与 assert 对比
| 特性 | assert | static_assert |
|---|---|---|
| 检查时机 | 运行时 | 编译时 |
| 条件类型 | 运行时表达式 | 编译时常量 |
| 失败结果 | 程序终止 | 编译失败 |
| 开销 | 有(运行时检查) | 无 |
| 用途 | 运行时假设 | 编译期约束 |
常见错误
运行时表达式:
int x = 10;
static_assert(x > 0, "x must be positive"); /* 错误:x 不是常量 */
/* 正确 */
#define X 10
static_assert(X > 0, "X must be positive");
最佳实践
- 编译期可确定的约束用
static_assert - 类型大小、结构体布局、配置值检查
- 提供清晰的错误信息
- C99 用 typedef 技巧模拟
- 与运行时
assert互补使用