我在某处看到断言通过以下方式与消息一起使用:
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
! (第一次,当false
循环检查其条件时;第二次,当for
正在评估传递的表达式时!)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!");
对于开关的意外默认情况,选项是
assert(!"message");
一个接受
const char*
并返回 true
的函数可能会让你免受各种警告:
#include <assert.h>
int always_true(const char *msg) {
return 1;
}
#define assert_msg(expr, msg) assert((expr) && always_true(msg))
就我而言,我更改了@pmg的答案以便能够控制输出。
(... && "message")
对我不起作用。
#include <assert.h>
#include <stdio.h>
#define __DEBUG__ 1
assert ((1 == 1) &&
(__DEBUG__ && printf(" - debug: check, ok.\n")) || !__DEBUG__);
我喜欢在 C 中这样做。这允许通过以下方式调用
assert
:
assert(expression);
assert(expression, "reason");
assert(expression, "reason %d", 11);
这是代码:
#define assert(cond, ...) \
if (!(cond)) \
_assert(#cond, __FILE__, __LINE__, #__VA_ARGS__ __VA_OPT__(,) ##__VA_ARGS__)
void _assert (const char* snippet, const char* file, int line, const char* message, ...)
{
print("assert failed %s:%d %s\n", file, line, snippet);
if (*message)
{
va_list arg;
va_start(arg, message);
char* data = va_arg(arg, char*);
vprintf(data, arg);
}
}
您可以编写自己的宏来提供与
_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
我还有一个宏
warn_bug()
,即使断言被禁用,它也会打印程序的名称、文件、行、函数、errno 值和字符串以及用户消息。其背后的原因是它不会破坏程序,但会警告可能存在错误。不过,如果 assert_msg
,您可以将 defined(NDEBUG)
定义为空。
根据以下链接 http://www.cplusplus.com/reference/clibrary/cassert/assert/
assert 只需要表达式。可能您正在使用一些重载函数。
根据此,只允许表达,因此您会收到此警告。