C++ 断言(0)是什么意思?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/34236653/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What does assert(0) mean?
提问by Smith Western
I had a question like this on one of my exams and I'm still not too sure how to answer it. I understand that assertions are ways to test your program, however I'm not too sure what assert(0)
is checking. Is this a trick question? It will always fail, but I don't understand why. What is it checking?
我在一次考试中遇到了这样的问题,但我仍然不太确定如何回答。我知道断言是测试程序的方法,但是我不太确定assert(0)
正在检查什么。这是一个技巧问题吗?它总是会失败,但我不明白为什么。它在检查什么?
Any explanation would be great, thanks.
任何解释都会很棒,谢谢。
采纳答案by djechlin
It will always fail. That's pretty much it. It will fail always for the same reason that "assert(x == 5)" will succeed whenever x = 5.
它总是会失败。差不多就是这样。它总是会失败,原因与每当 x = 5 时“assert(x == 5)”都会成功的原因相同。
If you're asking for an applicationthen you would put it in code blocks that really shouldn't happen.
如果你要一个应用程序,那么你会把它放在真正不应该发生的代码块中。
switch(suit) {
case CLUB:
case DIAMOND:
case HEART:
case SPADE:
// ...
default:
assert(0);
}
回答by Cheers and hth. - Alf
The C++ standard defers the definition of assert
to the C standard.
C++ 标准将 的定义推迟assert
到 C 标准。
”The
assert
macro puts diagnostic tests into programs; it expands to a void expression. When it is executed, if expression(which shall have a scalar type) is false (that is, compares equal to 0), the assert macro writes information about the particular call that failed (including the text of the argument, the name of the source file, the source line number, and the name of the enclosing function — the latter are respectively the values of the preprocessing macros__FILE__
and__LINE__
and of the identifier__func__
) on the standard error file in an implementation-defined format. It then calls theabort
function.
”在
assert
宏观使诊断测试进入程序; 它扩展为 void 表达式。执行时,如果表达式(应具有标量类型)为假(即比较等于 0),则断言宏会写入有关失败的特定调用的信息(包括参数的文本、调用的名称)源文件,源代码行号,和包围函数的名称-后者分别是预处理的宏的值__FILE__
和__LINE__
与标识符的__func__
)在一个实施方式定义的格式标准错误文件。然后调用该abort
函数。
In assert(0)
the 0
is interpreted as false
, so this assertion will always fail, or fire, when assertion checking is on.
在assert(0)
将0
被解释为false
,所以这种说法总是会失败,或火,当断言检查上。
Thus it asserts that
因此它断言
“The execution will never reach this point.”
“执行永远不会到这一步。”
In practice it can be difficult to make compilers shut up about the execution reaching or not reaching a given point. Often the compiler will first complain about the execution possibly reaching the end of a function without returning a value. Adding an assert(0)
there should ideally solve that issue, but then the compiler may complain about the assert
, or not recognize that it says you're already well aware of what it tries to warn about.
在实践中,很难让编译器对执行到达或未到达给定点闭嘴。通常编译器会首先抱怨执行可能到达函数的末尾而没有返回值。在assert(0)
理想情况下添加一个there 应该可以解决这个问题,但是编译器可能会抱怨assert
,或者没有意识到它说你已经很清楚它试图警告什么。
One (1)possible measure then is to also throw an exception at that point:
一(1) 种可能的措施是在此时也抛出异常:
auto foo( int x )
-> int
{
if( x == 1 ) { return 42; }
assert( 0 ); throw 0; // Should never get here!
}
Of course that double-whammy can be defined as a higher level macro. Regarding the exception type you may want to keep it as not a std::exception
, because this is not an exception intended to be caught by an ordinary catch
anywhere. Or, if you trust the standard exception hierarchy (it doesn't make sense to me, but) you can use a std::logic_error
.
当然,双重打击可以定义为更高级别的宏。关于异常类型,您可能希望将其保留为 not a std::exception
,因为这不是旨在被普通catch
任何地方捕获的异常。或者,如果您信任标准异常层次结构(这对我来说没有意义,但是)您可以使用std::logic_error
.
To turn off assert
assertion checking you can define the symbol NDEBUG
before including <assert.h>
.
要关闭assert
断言检查,您可以NDEBUG
在包含之前定义符号<assert.h>
。
This header has special support so that you can include it multiple times, with or without NDEBUG
defined.
此标头具有特殊支持,因此您可以在NDEBUG
定义或未定义的情况下多次包含它。
”A translation unit may include library headers in any order (Clause 2). Each may be included more than once, with no effect different from being included exactly once, except that the effect of including either
<cassert>
or<assert.h>
depends each time on the lexically current definition ofNDEBUG
.
”一个翻译单元可以包含任意顺序的库头文件(第 2 条)。每个都可以被包含多次,与只包含一次没有什么不同,除了包含
<cassert>
或的效果<assert.h>
每次都取决于 的词法当前定义NDEBUG
。
A reasonable definition of the double-whammy discussed above can likewise depend on NDEBUG
with no include guard, e.g.
上面讨论的双重打击的合理定义同样可以依赖于NDEBUG
不包含保护,例如
#include <stdexcept> // std::logic_error
#include <assert.h>
#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
Disclaimer: While I coded that up a number of times in the early 2000s, I cooked up the code above just for this answer, and while I did test it with g++ it may not necessarily be perfect.
免责声明:虽然我在 2000 年代初期对此进行了多次编码,但我只是为这个答案编写了上面的代码,虽然我确实用 g++ 对其进行了测试,但它不一定是完美的。
(1)See Basile Starynkevitch's answerfor discussion of another possibility, the g++-specific intrinsic __builtin_unreachable
.
(1)有关另一种可能性的讨论,请参阅Basile Starynkevitch 的回答,即 g++ 特定的内在函数__builtin_unreachable
。
回答by emlai
Yes, it will always fail.
是的,它总是会失败。
assert(0)
or assert(false)
is usually used to mark unreachable code, so that in debug mode a diagnostic message is emitted and the program is aborted when the supposedly unreachable is actually reached, which is a clear signal that the program isn't doing what we think it is.
assert(0)
orassert(false)
通常用于标记无法访问的代码,以便在调试模式下发出诊断消息并在实际到达假定无法访问时中止程序,这是一个明确的信号,表明程序没有按照我们认为的那样做。
回答by Basile Starynkevitch
In additionto other answers (notably thisone), if you are using a recent GCC(or Clang), you might consider using some GCC builtin, notably __builtin_unreachable()
instead of assert(0)
.
在另外的其他答案(尤其是这一次),如果您使用的是最近的海湾合作委员会(或铛),你可以考虑使用一些GCC内建,特别是__builtin_unreachable()
代替assert(0)
。
There are some differences: first, assert
can be disabled with -DNDEBUG
. And __builtin_unreachable
will change the way the compiler is optimizing your code.
有一些区别:首先,assert
可以用 禁用-DNDEBUG
。并且__builtin_unreachable
会改变编译器优化代码的方式。
Of course some compilers don't know about __builtin_unreachable
.
当然,有些编译器不知道__builtin_unreachable
.
And you could also consider calling some [[noreturn]]
C++ function (in C++11 or better) - or __attribute__((noreturn))
for GCC, such as abort()
您还可以考虑调用一些[[noreturn]]
C++ 函数(在 C++11 或更高版本中) - 或__attribute__((noreturn))
为GCC,例如abort()
BTW, assert(0)
is not exactly like throwing some exception (since exceptions can be caught)
顺便说一句,assert(0)
并不完全像抛出一些异常(因为可以捕获异常)