Search code examples
cmacrosunused-variables

How to elegantly fix this unused variable warning?


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

  • #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.