跳转至

static_assert 和 assert

  • 功能:
  • static_assert 进行编译时断言检查
  • 区别:
  • static_assert 是关键字,而 assert 是宏
  • assert 进行运行期检查,而 static_assert 在编译期检查
  • 示例
#include<assert.h>
int main()
{
    //assert不会在编译期报错,只有运行程序时,执行到这一步采取检查assert中表达式的值
    assert(1 + 2 < 2);
    //static_assert会在编译期检查,如vs会立即报错提示
    static_assert(1 + 2 < 2, "1+2>2");    
}
  • assert 源码分析: 当在程序中定义 NDEBUG 宏时,assert 宏辉展开成 (void)0,这可以使 assert 不产生任何断言作用。assert 展开后先执行 !!(expression) 表达式,如果真,则得 (void)true,否则,执行 (_wassert(_CRT_WIDE(#expression), _CRT_WIDE(__FILE__), (unsigned)(__LINE__)), 0),其中 _wassert 函数作用是将错误信息打印在控制台,并调用 std::abort() 终止程序。,0 的作用是利用逗号表达式的特性使 assert 宏执行后产生 (void)0 结果
#ifdef NDEBUG

    #define assert(expression) ((void)0)

#else

    _ACRTIMP void __cdecl _wassert(
        _In_z_ wchar_t const* _Message,
        _In_z_ wchar_t const* _File,
        _In_   unsigned       _Line
        );

    #define assert(expression) (void)(                                                       \
            (!!(expression)) ||                                                              \
            (_wassert(_CRT_WIDE(#expression), _CRT_WIDE(__FILE__), (unsigned)(__LINE__)), 0) \
        )

#endif

注意:(void)0 的作用使表达式仅仅可执行,却不能作为左值或右值,如 int i=(void)(1+2); 将会报错,表达式 1+2 会执行得到 3,但这个值经过 void 强制转为不完整类型,因此不能给 int 变量。