私はどこかで次のようにメッセージでアサートが使用されているのを見ました:
assert(("message", condition));
これは、gccが次の警告をスローすることを除いて、うまく機能しているようです。
warning: left-hand operand of comma expression has no effect
警告を停止するにはどうすればよいですか?
警告を停止するには、-Wno-unused-value
を使用します。 (オプション-Wall
には-Wunused-value
が含まれます)。
次のような別の方法を使用する方が良いと思います
assert(condition && "message");
試してください:
#define assert__(x) for ( ; !(x) ; assert(x) )
そのまま使用:
assert__(x) {
printf("assertion will fail\n");
}
アサートが失敗した場合にのみブロックを実行します。
重要な注意:このメソッドは、
x
が評価される場合、式x
を2回評価しますfalse
! (最初はfor
ループがその条件をチェックしているとき、2回目はassert
が渡された式を評価しているとき!)
フォーマットされたメッセージを渡したい場合は、次のマクロを使用できます。
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <assert.h>
#define clean_errno() (errno == 0 ? "None" : strerror(errno))
#define log_error(M, ...) fprintf(stderr, "[ERROR] (%s:%d: errno: %s) " M "\n", __FILE__, __LINE__, clean_errno(), ##__VA_ARGS__)
#define assertf(A, M, ...) if(!(A)) {log_error(M, ##__VA_ARGS__); assert(A); }
次に、printfのように使用します。
// With no args
assertf(self != NULL,"[Server] Failed to create server.");
// With formatting args
assertf((self->socket = u_open(self->port)) != -1,"[Server] Failed to bind to port %i:",self->port);
// etc...
出力:
[エラー](../src/webserver.c:180:errno:アドレスはすでに使用されています)[サーバー]ポート8080へのバインドに失敗しました:webserver:../src/webserver.c:180:server_run:アサーション `( self-> socket = u_open(self-> port))!= -1 'が失敗しました。
伝統により、(void)
は、意図的に式を無視していることをコンパイラに通知します。
/* picard.c, TNG S6E11. */
#define assertmsg(x, msg) assert(((void) msg, x))
assertmsg(2+2==5, "There! are! four! lights!");
_Static_assert(expr, msg)
と同じ使用法を提供する独自のマクロを作成できます。
_#include <assert.h>
#include <stdbool.h>
#include <stdio.h>
/*
* void assert_msg(bool expr, const char *msg);
*/
#if !defined(NDEBUG)
#define assert_msg(expr, msg) do \
{ \
const bool e_ = expr; \
\
if (!e_) { \
fputs(msg, stderr); \
fputc('\n', stderr); \
assert(e_); \
} \
} while (0)
#else
#define assert_msg(expr, msg) do \
{ \
\
if (!(expr)) \
warn_bug(msg); \
} while (0)
#endif
_
アサーションが無効になっている場合でも、プログラムの名前、ファイル、行、関数、errno値と文字列、およびユーザーメッセージを出力するマクロwarn_bug()
もあります。その背後にある理由は、それがプログラムを壊すことはありませんが、バグがおそらく存在するであろうことを警告するでしょう。ただし、defined(NDEBUG)
の場合、_assert_msg
_を空に定義するだけで済みます。
const char*
を受け取ってtrue
を返す関数は、おそらくあらゆる種類の警告からあなたを救うでしょう:
#include <assert.h>
int always_true(const char *msg) {
return 1;
}
#define assert_msg(expr, msg) assert((expr) && always_true(msg))