I'm working on some C code that does lot's of error reporting and logging when a DEBUG
flag is set, which sometimes produces unused variable warnings when compiling with the DEBUG
flag not set.
#ifdef DEBUG
#define CHECK(expr) foo(expr)
#else
#define CHECK(expr)
#endif /* DEBUG */
int x = bar(a, b, c); /* bar has to be called for both DEBUG begin defined and undefined */
CHECK(x == SOME_VALUE); /* Produces an "unused variable" warning if DEBUG is undefined
Edit: Just a little reminder (not sure if it is of any consequence): the argument for the CHECK
macro is an expression, not a single variable.
For this pattern, what is the best way to get rid of the unused variable warning?
What I tried/though of:
#ifdef DEBUG
int x = bar(a, b, c);
#else
bar(a, b, c);
#endif
CHECK(x == SOME_VALUE);
and then, to avoid writing the call to bar
(which is more complicated in the actual call) twice:
#ifdef DEBUG
int x =
#endif
bar(a, b, c);
CHECK(x == SOME_VALUE);
However, I feel like this is not exactly a clean and readable solution. Is there a better way? Note that for performance reasons the CHECK(expr)
macro should not produce any code if DEBUG
is undefined (EDIT: and thus, expr
should not be evaluated).
Is there a more elegant way than the one I outlined above?
Solution: If variable <variable_name> or function <function_name> is not used, it can be removed. If it is only used sometimes, you can use __attribute__((unused)) . This attribute suppresses these warnings.
They are warnings, if they were errors they had the bad effect of failing the compilation. Unused variable warnings are emitted during compiletime and should be a hint to you as the developer, that you might have forgotten to actually process a value that you have bound to a name. Thats the main reason for the warning.
#ifdef DEBUG
#define CHECK(x) x
#else
#define CHECK(x) ((void)sizeof((void)(x),0))
#endif
I think this addresses all of the possible issues :
sizeof
ensures that the expression is not evaluated at all, so its side-effects don't happen. That is to be consistent with the usual behaviour of debug-only constructs, such as assert
.((x), 0)
uses the comma operator to swallow the actual type of (x)
. This is to prevent VLAs from triggering evaluation.(void)
explicitly ignores the result of (x)
and sizeof
so no "unused value" warning appears.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With