【C语言指南】assert宏 使用详解

316 阅读4分钟

文章目录

一、assert简介

二、assert使用方法和规则

2.1 头文件

2.2 原型

2.3 功能

2.4 示例

2.5 assert的打开与关闭

三、注意事项

3.1 运行效率问题

3.2 assert只适用于调试版本

3.3 资源释放与清理

3.4 过度依赖

四、总结

一、assert简介

assert是一个在C语言中用于调试的宏 ,用于在运行时确保程序符合指定条件,如果不符合,就报错终止运行。这个宏常常被称为“断言”

二、assert使用方法和规则

2.1 头文件

注意:assert是宏,而不是函数。在C的assert.h头文件中。

2.2 原型

​assert(表达式);

#include <assert.h>
assert(expression);

2.3 功能

assert() 宏接受⼀个表达式作为参数。

如果该表达式为真(返回值非零), assert() 不会产生任何作用,程序继续运行;

如果该表达式为假(返回值为零), assert() 就会报错,在标准错误流 stderr 中写入⼀条错误信息,显示没有通过的表达式,以及包含这个表达式的⽂件名和行号。(而这也正是使用assert的优势,它能自动标识文件和出问题的行号)

2.4 示例

比如在下面这段代码中设置了两个assert语句

#include<stdio.h>
#include<assert.h>
int main()
{
	int a = 10;
	int* p1 = &a;
	assert(p1 != NULL);//表达式为真,assert不执行

	int* p2 = NULL;
	assert(p2 != NULL);//表达式为假,assert执行,程序崩溃

	return 0;
}

执行第一条assert语句,表达式为真,assert不执行

执行第二条assert语句,表达式为假,assert执行,程序崩溃

​编辑

并且会在标准错误流中输出错误的语句和行号

​编辑

2.5 assert的打开与关闭

assert的关闭

如果已经确认程序没有问题,不需要再做断⾔,就在 #include <assert.h> 语句的前⾯,定义⼀个宏 NDEBUG 。然后,重新编译程序,编译器就会禁⽤⽂件中所有的 assert() 语句。

#define NDEBUG
#include<stdio.h>
#include<assert.h>
int main()
{
	int a = 10;
	int* p1 = &a;
	assert(p1 != NULL);

	int* p2 = NULL;
	assert(p2 != NULL);//即使表达式为假,assert也不会执行

	return 0;
}

​编辑

assert的重新启用

如果程序又出现问题,可以移除这条 #define NDBUG 指令(或者把它注释掉),再次编译,这样就重新启用了 assert() 语句。

​编辑

三、注意事项

3.1 运行效率问题

由于assert引入了额外的检查,降低了程序运行效率,如果上述一段代码拿到编译器中运行就会发现运行时间大大增加,并且过度使用可能降低代码可读性和维护性,应在必要时谨慎使用。

3.2 assert只适用于调试版本

assert`仅适用于开发和测试阶段,在发布版本中通常需要移除或者替换为更完整的错误处理机制,因为它不能提供用户友好的错误提示,且会导致程序直接崩溃。

一般在当前的集成开发环境,在 Release 版本中,直接就是优化掉了。这样在debug版本写有利于程序员排查问题,在 Release 版本不影响用户使用时程序的效率。

3.3 资源释放与清理

由于assert通常会导致程序立即终止,它可能无法完成必要的资源释放与清理工作,尤其是在涉及到内存管理等场景时,可能导致资源泄露等问题。

3.4 过度依赖

过度使用assert可能导致代码逻辑过分依赖于开发阶段的检查,而忽略了对异常情况的实际处理,使得代码在release模式下可能出现意料之外的行为。

四、总结

assert是一个强大的调试工具,可以大大提高程序开发效率,但在实际项目中应根据实际情况合理使用,并结合其他健壮的错误处理机制以确保程序在所有环境下的稳定性和可靠性。