I saw somewhere assert used with a message in the following way:
assert(("message", condition));
This seems to work great, except that gcc throws the following warning:
warning: left-hand operand of comma expression has no effect
How can I stop the warning?
-
See this related question.razlebe– razlebe2011年05月03日 10:00:21 +00:00Commented May 3, 2011 at 10:00
10 Answers 10
Use -Wno-unused-value to stop the warning; (the option -Wall includes -Wunused-value).
I think even better is to use another method, like
assert(condition && "message");
5 Comments
condition. Does the compiler also warn with just assert(condition);?assert((Msg, Cond)); works without warnings on VS 2008.assert((<cond>) && "msg"); causes CppCheck (v1.90) to generate an "incorrectStringBooleanError" warning.Try:
#define assert__(x) for ( ; !(x) ; assert(x) )
use as such:
assert__(x) {
printf("assertion will fail\n");
}
Will execute the block only when assert fails.
IMPORTANT NOTE: This method will evaluate expression
xtwice, in casexevaluates tofalse! (First time, when theforloop is checking its condition; second time, when theassertis evaluating the passed expression!)
5 Comments
assert__(foo); and the semicolon will end the block.(x) returns true only once: string("a") a; assert__(a.append("b") == "ab") { ... }for and not if?assert stops the program execution and printf is not called.assert to stop the program before printf because assert is not called until after printf.If you want to pass a formatted message, you could use the following macros:
#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); }
Then use it like 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...
Output:
[ERROR] (../src/webserver.c:180: errno: Address already in use) [Server] Failed to bind to port 8080: webserver: ../src/webserver.c:180: server_run: Assertion `(self->socket = u_open(self->port)) != -1' failed.
1 Comment
assertf(x == y, "x does not equal y") violates the standard. This is easily rectified via assertf(x == y, "%s", "x does not equal y") however). It also relies on the gcc extension ##__VA_ARGS__ which isn't necessarily a bad thing, but it does make it less portableBy tradition, (void) communicates to the compiler that you are knowingly ignoring an expression:
/* picard.c, TNG S6E11. */
#define assertmsg(x, msg) assert(((void) msg, x))
assertmsg(2+2==5, "There! are! four! lights!");
Comments
I like to do it this way in C. This allows calling assert the following ways:
assert(expression);
assert(expression, "reason");
assert(file, "cannot open %s", filename);
Here is the code:
#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);
}
}
Comments
For unexpected default case of a switch, an options is
assert(!"message");
A function that takes const char* and returns true would probably save you from all sorts of warnings:
#include <assert.h>
int always_true(const char *msg) {
return 1;
}
#define assert_msg(expr, msg) assert((expr) && always_true(msg))
2 Comments
(void*)msgIn my case, I changed @pmg's answer to be able to control the output. The (... && "message") didn't work for me.
#include <assert.h>
#include <stdio.h>
#define __DEBUG__ 1
assert ((1 == 1) &&
(__DEBUG__ && printf(" - debug: check, ok.\n")) || !__DEBUG__);
1 Comment
NDEBUG instead of __DEBUG__. It's the standard way to do this as defining NDEBUG automatically disables all assets.You could write your own macro that provides the same usage of _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
I also have a macro warn_bug() that prints the name of the program, the file, the line, the function, the errno value and string, and a user message, even if asserts are disabled. The reason behind it is that it won't break the program, but it will warn that a bug will probably be present. You could just define assert_msg to be empty if defined(NDEBUG), though.
Comments
According to following link http://www.cplusplus.com/reference/clibrary/cassert/assert/
assert is expecting only expression. May be you are using some overloaded function.
According to this, only expression is allowed and thus you are getting this warning.
2 Comments
assert( ("message", condition) ); This is C: no overloading.