【C/CPP】assert断言与static_assert静态断言

一、断言

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;
}


需要注意的是:

  1. assert是在程序运行的时候进行错误检查的,而不是编译的时候,频繁的调用会极大的影响程序的性能,增加额外的开销。所以一般而言,assert用在DEBUG版本中捕捉不应该发生的非法情况,如参数类型与参数范围等
  2. 每个assert只检验一个条件,以免断言失败,无法直观的判断是哪个条件失败
  3. 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.");
}


如上所示,程序在64位系统的64位编译器上进行了报错。

三、断言小结

  1. assert是运行期断言,只能发现运行期间的错误,不能提前到编译期发现错误,对性能有较大影响,在发行版本中,assert都会被关掉
  2. #error仅仅能在预编译时显示一个错误信息,做不了更进一步的分析
  3. static_assert恰好整合了assert#error的优点,在编译时进行断言
  4. C++中,static_assert主要用于检查模板参数是否符合期望
  5. C++20中引入了concept来进一步更好的实现模板参数的编译时类型匹配检查

你可能感兴趣的:(C语言,C++)