Old unused variable trick for assert : sizeof

Started by
5 comments, last by BitMaster 8 years, 5 months ago

Hi,

An old trick was to use sizeof against cast-to-void for unused variable for assert to not have evaluation of the parameter.

Is it still valid nowadays or cast-to-void works on all case nowadays ?

Thanks

Advertisement
I have no idea what you're trying to do. Can you post some code that demonstrates what you want?

Wielder of the Sacred Wands
[Work - ArenaNet] [Epoch Language] [Scribblings]

I've always just relied on C4100 to tell me when I have unused variables (which won't even let me compile with /Wall and /WX set).

I believe the OP means he wants to disable C4100 for some unused variables.

The trick he's referring to comes in two parts.

First, casting a value to void in order to evaluate (use) it without generating other warnings about statements with no effect.

(void)foo;

Second, using the sizeof operator so the expression is in an unevaluated context, nullifying any side effects of expressions.

sizeof(some_expensive_call())

This is useful for debug macros that you might want to disable in some configurations. It's not uncommon to have a parameter or variable that's only used for debugging.

void DoSomething(int foo, char const* debug_name) {
  DEBUG_MESSAGE(debug_name);
  stuff(foo);
}

If in the above the DEBUG_MESSAGE macro were compiled into a no-op, debug_name would become an unused variable and trigger C4100 and its ilk.

The void cast trick makes it a referenced variable. But if the void cast is applied indiscriminately to DEBUG_MESSAGE arguments when disabled, functions with side effects would still be evaluated even when debug messages are disabled.

void DoSomething(Object* obj) {
  DEBUG_MESSAGE(obj->GetDebugName());
  stuff(obj);
}

The sizeof operator thus makes those unevaluated while still making variables be "used" from the compiler's standpoint.

A good way to write a macro like DEBUG_MESSAGE would be to do something similar to what the OP was talking about.

#ifdef DEBUG
#  define DEBUG_MESSAGE(msg) puts((msg))
#else
#  define DEBUG_MESSAGE(msg) (void)sizeof((msg), 1)
#endif

Note that use of the ,1 so that if msg evaluates to void it will still compile without error.

So to answer the OP's question: yes, the trick is still relevant, because macros are a pain in the butt, but they're the only solution we have to certain problems (like zero-overhead debug loggers).

Sean Middleditch – Game Systems Engineer – Join my team!

Nice breakdown, thanks!

Wielder of the Sacred Wands
[Work - ArenaNet] [Epoch Language] [Scribblings]

I use slightly different technique,

void Foo(int /*SomeParameter*/)

This way, I get also quick documentation and shut up compiler warning.

That does not really help for what was asked and what SeanMiddleditch described: the point is that the arguments are needed when the assert is evaluated.

This topic is closed to new replies.

Advertisement