assert()与消息

时间:2011-05-03 09:54:06

标签: c gcc compiler-warnings assert

我通过以下方式看到某处断言与消息一起使用:

assert(("message", condition));

这似乎很有效,除了gcc抛出以下警告:

warning: left-hand operand of comma expression has no effect

如何停止警告?

9 个答案:

答案 0 :(得分:64)

使用-Wno-unused-value停止警告; (选项-Wall包括-Wunused-value)。

我认为更好的方法是使用其他方法,例如

assert(condition && "message");

答案 1 :(得分:20)

尝试:

#define assert__(x) for ( ; !(x) ; assert(x) )

使用原样:

assert__(x) {
    printf("assertion will fail\n"); 
}

仅在断言失败时执行该块。

  

重要提示: 此方法将评估表达式x两次,以防x评估为false(第一次,for循环检查其条件;第二次,assert正在评估传递的表达式!)

答案 2 :(得分:11)

如果要传递格式化消息,可以使用以下宏:

#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:错误:地址已在使用中)   [服务器]无法绑定到端口8080:webserver:   ../src/webserver.c:180:server_run:断言`(self-&gt; socket =   u_open(self-&gt; port))!= -1&#39;失败。

基于http://c.learncodethehardway.org/book/ex20.html

答案 3 :(得分:0)

您可以编写自己的宏,以提供与_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)定义为空。

答案 4 :(得分:0)

根据传统,(void)向编译器传达您故意忽略表达式的信息:

/* picard.c, TNG S6E11. */
#define assertmsg(x, msg) assert(((void) msg, x))
assertmsg(2+2==5, "There! are! four! lights!");

答案 5 :(得分:0)

使用const char*并返回true的函数可能会为您避免各种警告:

#include <assert.h>

int always_true(const char *msg) {
    return 1;
}

#define assert_msg(expr, msg) assert((expr) && always_true(msg))

答案 6 :(得分:0)

对于开关的意外默认情况,一个选项是

assert(!"message");

答案 7 :(得分:0)

就我而言,我更改了@pmg 的答案以便能够控制输出。 (... && "message") 对我不起作用。

#include <assert.h>
#include <stdio.h>

#define __DEBUG__ 1

assert ((1 == 1) && 
       (__DEBUG__ && printf("  - debug: check, ok.\n")) || !__DEBUG__);

答案 8 :(得分:-9)

根据以下链接 http://www.cplusplus.com/reference/clibrary/cassert/assert/

断言只期待表达。可能是你正在使用一些重载功能。

根据这一点,只允许表达式,因此您会收到此警告。