assert.h
<assert.h> 提供 assert 宏,用于在开发阶段检查程序假设。如果断言条件为假,程序输出错误信息并终止。assert 是调试的有力工具,帮助在问题发生点立即发现错误,而不是让错误传播。
assert 基本用法
#include <assert.h>
void divide(int a, int b)
{
assert(b != 0); /* 假设:除数不为零 */
printf("%d\n", a / b);
}
divide(10, 2); /* 正常 */
divide(10, 0); /* 断言失败,程序终止 */
断言失败输出:
Assertion failed: b != 0, file test.c, line 5
禁用断言
定义 NDEBUG 宏后,所有 assert 被禁用:
#define NDEBUG /* 必须在 assert.h 之前 */
#include <assert.h>
/* assert 不再生效 */
编译时定义:
gcc -DNDEBUG program.c /* 禁用断言 */
使用场景
函数前置条件:
void process_array(int *arr, int n)
{
assert(arr != NULL); /* 指针非空 */
assert(n > 0); /* 大小合法 */
/* 处理 */
}
不变量检查:
void sort(int *arr, int n)
{
/* 排序 */
/* 验证排序结果(调试模式) */
for (int i = 1; i < n; i++)
assert(arr[i] >= arr[i - 1]);
}
不可能到达的分支:
switch (type) {
case TYPE_A: /* ... */ break;
case TYPE_B: /* ... */ break;
default:
assert(0 && "Unknown type"); /* 不应到达 */
}
常见错误
副作用在断言中:
assert((fp = fopen("data.txt", "r")) != NULL);
/* NDEBUG 时 fopen 不执行! */
/* 正确 */
fp = fopen("data.txt", "r");
assert(fp != NULL);
用 assert 替代错误处理:
/* 错误:用户输入不应断言 */
assert(scanf("%d", &x) == 1);
/* 正确 */
if (scanf("%d", &x) != 1) {
/* 错误处理 */
}
最佳实践
- 断言检查程序员的假设(内部错误)
- 不断言外部输入(用户、文件、网络)
- 断言中不要有副作用
- 发布版本用
NDEBUG禁用 - 断言信息应帮助定位问题