assert
是一个宏函数,其原型定义在assert.h
中:
#ifdef NDEBUG
#define assert(condition) ((void)0)
#else
#define assert(condition)
#endif
一般在调试版本中使用,作用是在程序运行的时候将条件condition
的表达式的逻辑值与0进行比较,若相等,则在标准错误输出上输出实现指定的诊断信息,并调用abort
终止程序执行,如下测试
#include
#include
#include
int main(void)
{
double x = -1.0;
assert(x >= 0.0);
std::cout << sqrt(x) << std::endl;
return 0;
}
assert
是在程序运行的时候进行错误检查的,而不是编译的时候,频繁的调用会极大的影响程序的性能,增加额外的开销。所以一般而言,assert
用在DEBUG
版本中捕捉不应该发生的非法情况,如参数类型与参数范围等assert
只检验一个条件,以免断言失败,无法直观的判断是哪个条件失败assert
是用来避免显而易见的错误的,而不是处理异常的。错误和异常是不一样的,错误是不应该出现的,异常是不可避免的。C/C++异常可以通过条件判断来处理,其它语言有各自的异常处理机制。在C11
中,引入了关键字宏static_assert
,也是定义在assert.h
中,原型如下:(在C++中也一直沿用)
#define static_assert _Static_assert
_Static_assert
是一个声明,其格式如下
_Static_assert (condition, message)
作用是在编译的时候判断条件condition
的值,如果为0,则报错输出message
信息,且不生成.elf
可执行程序。如下所示,如果有程序只能在32系统上的32位的编译器上编译,则可使用如下测试代码:
#include
void is_32(void)
{
static_assert(sizeof(void *) == 4, "64-bit code generation is not supported.");
}
assert
是运行期断言,只能发现运行期间的错误,不能提前到编译期发现错误,对性能有较大影响,在发行版本中,assert
都会被关掉#error
仅仅能在预编译时显示一个错误信息,做不了更进一步的分析static_assert
恰好整合了assert
和#error
的优点,在编译时进行断言C++
中,static_assert
主要用于检查模板参数是否符合期望C++20
中引入了concept
来进一步更好的实现模板参数的编译时类型匹配检查