私の試験の1つでこのような質問がありましたが、まだどのように答えればよいかわかりません。アサーションはプログラムをテストする方法であることを理解していますが、assert(0)
がチェックしていることはあまりわかりません。これはトリックの質問ですか?常に失敗しますが、その理由はわかりません。何をチェックしていますか?
どんな説明でも素晴らしいでしょう、ありがとう。
常に失敗します。それはほとんどそれです。 x = 5の場合は常に「assert(x == 5)」が成功するのと同じ理由で失敗します。
applicationを要求している場合、実際には発生しないはずのコードブロックに配置します。
switch(suit) {
case CLUB:
case DIAMOND:
case HEART:
case SPADE:
// ...
default:
assert(0);
}
C++標準は、assert
の定義をC標準に委ねています。
”
assert
マクロは、診断テストをプログラムに入れます。 void式に展開されます。実行時に、expression(スカラー型でなければならない)がfalse(つまり、0に等しい)である場合、assertマクロは失敗した特定の呼び出しに関する情報を書き込みます(引数のテキスト、ソースファイルの名前、ソース行番号、囲んでいる関数の名前を含みます。後者はそれぞれ前処理マクロ___FILE__
_および___LINE__
_の値です。実装定義形式の標準エラーファイルの識別子___func__
_)。次に、abort
関数を呼び出します。
assert(0)
では、_0
_はfalse
として解釈されるため、このアサーションは常に失敗するか、またはfire 、アサーションチェックがオンの場合。
したがって、それは
「実行がこのポイントに達することはありません。」
実際には、実行が特定のポイントに到達するか到達しないかについてコンパイラーを黙らせるのは困難です。多くの場合、コンパイラは最初に、値を返さずに関数の最後に到達する可能性について最初に文句を言います。そこにassert(0)
を追加すると、理想的にはその問題を解決するはずですが、コンパイラはassert
について文句を言うか、警告しようとしていることにすでに気付いていると言っていることに気付かない場合があります。
1 (1)可能な対策は、その時点で例外もスローすることです。
_auto foo( int x )
-> int
{
if( x == 1 ) { return 42; }
assert( 0 ); throw 0; // Should never get here!
}
_
もちろん、そのダブルワーミーは、より高いレベルのマクロとして定義できます。例外の種類については、_std::exception
_ではなく、通常のcatch
によってキャッチされることを意図した例外ではないため、そのままにしておくことができます。または、標準の例外階層を信頼する場合(私には意味がありませんが)、_std::logic_error
_を使用できます。
assert
アサーションチェックをオフにするには、_<assert.h>
_を含める前にシンボルNDEBUG
を定義できます。
このヘッダーには特別なサポートがあるため、NDEBUG
が定義されているかどうかに関係なく、複数回含めることができます。
”翻訳単位には、ライブラリヘッダーを任意の順序で含めることができます(第2項)。 _
<cassert>
_または_<assert.h>
_を含めることの効果は、毎回NDEBUG
の字句的に定義されたものに依存することを除いて、それぞれを複数回含めることができます。 。
上記のダブルワミーの合理的な定義は、インクルードガードのない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
_
免責事項:2000年代前半に何度もコーディングしましたが、この答えのために上記のコードを作成しましたが、g ++でテストしましたが、必ずしも完璧ではないかもしれません。
(1) 別の可能性、g ++固有の組み込み____builtin_unreachable
_については、 Basile Starynkevitchの答え を参照してください。
はい、常に失敗します。
assert(0)
またはassert(false)
は通常、到達不能コードをマークするために使用されるため、デバッグモードでは診断メッセージが出力され、到達不能と思われる場合にプログラムが中止されます。実際に到達しました。これは、プログラムが想定どおりに動作していないことを示す明確なシグナルです。
他の回答(特に this one)へのadditionで、最近の [〜#〜] gcc [〜#〜]を使用している場合 (または Clang )、 GCCビルトイン 、特に__builtin_unreachable()
の代わりにassert(0)
を使用することを検討できます。
いくつかの違いがあります:最初に、assert
は-DNDEBUG
で無効にできます。そして、__builtin_unreachable
は、コンパイラがコードを最適化する方法を変更します。
もちろん、一部のコンパイラは__builtin_unreachable
について知りません。
また、[[noreturn]]
C++関数(C++ 11以降)の呼び出しを検討することもできます-または __attribute__((noreturn))
for [〜#〜] gcc [〜#〜] 、abort()
など
ところで、assert(0)
は、例外をスローするのとまったく同じではありません(例外をキャッチできるため)