assert(0)是什么意思?

在我的一次考试中我有这样的问题,我仍然不太清楚如何回答它。 我知道断言是测试程序的方法,但是我不太清楚assert(0)正在检查什么。 这是一个棘手的问题吗? 它总会失败,但我不明白为什么。 什么检查?

任何解释都会很棒,谢谢。

C ++标准将assert的定义推迟到C标准。

C99§7.2/ 2:

assert宏将诊断测试纳入程序; 它扩展为void表达式。 当它被执行时,如果表达式 (它应具有标量类型)为假(即,比较等于0),则断言宏写入有关失败的特定调用的信息(包括参数的文本,名称源文件,源行号和封闭函数的名称 – 后者分别是实现定义格式的标准错误文件上的预处理宏__FILE____LINE__以及标识符__func__的值。 然后它调用abort函数。


assert(0)0被解释为false ,因此当断言检查打开时,此断言将始终失败或触发

因此,它断言

“执行永远不会达到这一点。”

在实践中,可能难以使编译器关闭执行达到或未达到给定点。 通常,编译器会首先抱怨执行可能到达函数的末尾而不返回值。 添加一个assert(0)应该理想地解决这个问题,但是编译器可能会抱怨assert ,或者没有认识到它说你已经很清楚它试图警告的内容。

然后,一(1)种可能的措施是在此时抛出exception:

 auto foo( int x ) -> int { if( x == 1 ) { return 42; } assert( 0 ); throw 0; // Should never get here! } 

当然,双重打击可以定义为更高级别的宏。 关于exception类型,您可能希望将其保留为std::exception ,因为这不是exception捕获的exception。 或者,如果您信任标准exception层次结构(对我来说没有意义,但是),您可以使用std::logic_error


要关闭assert断言检查,可以在包含之前定义符号NDEBUG

此标头具有特殊支持,因此您可以多次包含它,无论是否定义了NDEBUG

C ++11§17.6.2.2/ 2:

翻译单元可以包括任何顺序的图书馆标题(第2条)。 每个都可以被包含多次,除了包含效果每次都取决于NDEBUG的词法当前定义之外,没有任何效果与仅被包含一次有效。

上面讨论的双重打击的合理定义同样可以取决于没有包含防护的NDEBUG ,例如

文件assert_should_never_get_here.hpp

 #include  // std::logic_error #include  #undef ASSERT_SHOULD_NEVER_GET_HERE #ifdef NDEBUG # define ASSERT_SHOULD_NEVER_GET_HERE() \ throw std::logic_error( "Reached a supposed unreachable point" ) #else # define ASSERT_SHOULD_NEVER_GET_HERE() \ do{ \ assert( "Reached a supposed unreachable point" && 0 ); \ throw 0; \ } while( 0 ) #endif 

免责声明:虽然我在21世纪初对其进行了多次编码,但为了这个答案我编写了上面的代码,虽然我用g ++进行了测试,但它可能不一定是完美的。


(1)参见Basile Starynkevitch关于另一种可能性的讨论的答案 ,g ++特定的内在__builtin_unreachable

它总会失败。 这就是它。 它总是会失败的原因是,只要x = 5,“assert(x == 5)”就会成功。

如果你要求一个应用程序,那么你会把它放在真正不应该发生的代码块中。

 switch(suit) { case CLUB: case DIAMOND: case HEART: case SPADE: // ... default: assert(0); } 

是的,它总会失败。

assert(0)assert(false)通常用于标记无法访问的代码 ,因此在调试模式下会发出诊断消息,并在实际到达所谓的无法访问时中止程序,这是一个明确的信号,即程序不是做我们认为的事情。

除了其他答案(特别是这个 ),如果您使用的是最近的GCC (或Clang ),您可以考虑使用一些GCC内置 ,特别是__builtin_unreachable()而不是assert(0)

存在一些差异:首先,可以使用-DNDEBUG禁用-DNDEBUG 。 而__builtin_unreachable将改变编译器优化代码的方式。

当然有些编译器不了解__builtin_unreachable

您也可以考虑为GCC调用一些[[noreturn]] C ++函数(在C ++ 11或更高版本中)或__attribute__((noreturn)) ,例如abort()

顺便assert(0)一下, assert(0)并不像抛出一些exception(因为可以捕获exception)