65

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?

asked May 3, 2011 at 9:54
1
  • See this related question. Commented May 3, 2011 at 10:00

10 Answers 10

106

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");
answered May 3, 2011 at 10:10
Sign up to request clarification or add additional context in comments.

5 Comments

Nice one, I usually do assert(condition /* message */).
This sometimes gives "Conditional expression is constant" warning in Visual Studio. Any ideas on how to remove the warning without suppressing it?
@Samaursa: you probably have an issue with plain condition. Does the compiler also warn with just assert(condition);?
It does not. The interesting thing is that OP's original problem code is the solution to VS's warnings! assert((Msg, Cond)); works without warnings on VS 2008.
assert((<cond>) && "msg"); causes CppCheck (v1.90) to generate an "incorrectStringBooleanError" warning.
23

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 x twice, in case x evaluates to false! (First time, when the for loop is checking its condition; second time, when the assert is evaluating the passed expression!)

Peter Varo
12.4k7 gold badges61 silver badges81 bronze badges
answered Jun 9, 2012 at 8:20

5 Comments

The nice thing about this is that you can omit the message if you want by using assert__(foo); and the semicolon will end the block.
Such implementation will not work if (x) returns true only once: string("a") a; assert__(a.append("b") == "ab") { ... }
Why for and not if?
This does not seem to work in GCC. Failing assert stops the program execution and printf is not called.
@vil It is not possible for assert to stop the program before printf because assert is not called until after printf.
14

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.

Based on http://c.learncodethehardway.org/book/ex20.html

answered Mar 29, 2014 at 14:57

1 Comment

This, unfortunately, isn't portable. C99 requires that you use at least one of the optional arguments in a variadic macro (e.g this: 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 portable
5

By 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!");
answered Nov 11, 2019 at 10:02

Comments

3

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);
 }
}
answered Mar 19, 2024 at 0:17

Comments

1

For unexpected default case of a switch, an options is

assert(!"message");
answered May 8, 2021 at 2:31

3 Comments

This seems to be always false. Where is the condition that is being tested?
This useful for unexpected default case of a switch.
That, while true, doesn't have anything to do with the original question.
0

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))
answered Mar 29, 2020 at 3:56

2 Comments

Definitely not from "unused parameter" warnings.
That's easy to fix: just (void*)msg
0

In 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__);
answered May 20, 2021 at 11:31

1 Comment

Try NDEBUG instead of __DEBUG__. It's the standard way to do this as defining NDEBUG automatically disables all assets.
-1

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.

answered Sep 24, 2019 at 9:10

Comments

-11

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.

answered May 3, 2011 at 10:13

2 Comments

The inner parenthesis make it ok: assert( ("message", condition) ); This is C: no overloading.
Don't see what relevance a C++ website has to a C question.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.