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)