前言
这篇博客来聊一聊C/C++的断言机制。
嵌入式驱动学习专栏将详细记录博主学习驱动的详细过程,未来预计四个月将高强度更新本专栏,喜欢的可以关注本博主并订阅本专栏,一起讨论一起学习。现在关注就是老粉啦!
目录
- 前言
- 1. 断言介绍
- 1.1 断言的概念
- 1.2 断言的实现
- 1.3 禁用断言
- 2. 静态断言
- 2.1 使用案例
- 2.2 优点
- 3. 运行时断言
- 3.1 assert使用
- 3.2 assert注意事项
- 参考资料
1. 断言介绍
1.1 断言的概念
断言就是用于在代码中捕捉这些假设,可以将断言看作是异常处理的一种高级形式。
断言表示为一些布尔表达式,程序员相信在程序中的某个特定点该表达式值为真。可以在任何时候启用和禁用断言验证,因此可以在测试时启用断言,而在部署时禁用断言。
最终用户在遇到问题时可以重新起用断言。它可以快速发现并定位软件问题,同时对系统错误进行自动报警。断言可以对在系统中隐藏很深,用其它手段极难发现的问题可以用断言来进行定位,从而缩短软件问题定位时间,提高系统的可测性。
断言的本质就是if ... else ...
判断:
if (假设为true) {程序正常运行;
} else {报错并终止程序
}
那为什么还要断言呢?如果全是if ... else...
的话就会有无数个if
语句,甚至可能一个if语句的作用阈从文件头到文件尾。并且使用断言的时机,大部分都是偶然事件,只是要验证的假设,仅仅想测试一下最坏的情况是否发生。
除此以外,断言的assert()宏只有Debug版本才有效,Release中则被忽略。
1.2 断言的实现
在使用断言时,需要添加头文件:#include <assert.h>
断言是assert(expression)
,这是一个宏!!!!
void assert( int expression );
assert
计算表达式,如果值为假,那么先想stderr
打印一条错误信息,然后调用abort
来终止程序运行。
1.3 禁用断言
调试结束后,可以在#include语句之前插入#define NDEBUG来禁用assert调用:
#define NDEBUG
#include <assert.h>
2. 静态断言
2.1 使用案例
静态断言主要是用来约束程序在编译时要满足的一定要求,是在c++11中引入的。
其定义如下所示:
static_assert(常量表达式,提示字符串);
如果第一个参数常量表达式的值为真(true或者非零值),那么static_assert
不做任何事情,就像它不存在一样,否则会产生一条编译错误,错误位置就是该static_assert
语句所在行。错误提示就是第二个参数提示字符串。
#include <assert.h>int main(void) {static_assert(false, "This is an error");return 0;
}
在IDE中就会报错提示。并且下面的错误提示就是后面自己写的错误提示。
2.2 优点
1、使用
static_assert
,我们可以在编译期间发现更多的错误,提前找出错误的原因。
2、static_assert
可以用在全局作用域中,命名空间中,类作用域中,函数作用域中,几乎可以不受限制的使用。
3、编译器在遇到一个static_assert
语句时,通常立刻将其第一个参数作为常量表达式进行演算,但如果该常量表达式依赖于某些模板参数,则延迟到模板实例化时再进行演算,这就让检查模板参数成为了可能。
4、由于之前有望加入C++0x标准的concepts提案最终被否决了,因此对于检查模板参数是否符合期望的重任,就要靠static_assert来完成了,所以如何构造适当的常量表达式,将是一个值得探讨的话题。
5、性能方面,由于是static_assert编译期间断言,不生成目标代码,因此static_assert不会造成任何运行期性能损失
3. 运行时断言
3.1 assert使用
运行时断言可以在程序运行过程中,判断一些支持程序正常运行的假设性条件是否满足。
上面1.3中的assert
宏就是动态断言
3.2 assert注意事项
可以在函数开始处检验传入参数的合法性
int readNum(int n) {assert(n > 0);return 1;
}
每个assert
只检验一个条件,因为同时检验多个条件时,如果断言失败,无法直观的判断是哪个条件失败
// 不要写成这样
assert(n > 0 && n < maxBound);
// 最好写成这样
assert(n > 0);
assert(n < maxBound);
不能使用改变环境的语句,因为assert
只在DEBUG
个生效,如果这么做,会使用程序在真正运行时遇到问题
// 不要写成这样
assert(i++ > 10);
// 最好写成这样
assert(i > 10);
i++;
assert
和后面的语句应空一行,以形成逻辑和视觉上的一致感
有的地方,assert
不能代替条件过滤
参考资料
[1] C语言之断言的一些理解
[2] c++11中静态断言static_assert