cmacrosc-preprocessor

What does the c precompiler do with macros defined as (void)0


I have some macros that are defined based on compiler flags. I'm trying to decide whether I would rather have the macro defined as (void)0 or have it undefined and cause a compile time error.

i.e.

#ifdef DEBUG
  #define PRINTF(...) printf(__VA_ARGS__)
#else
  #define PRINTF(...) (void)0
#endif

int main(void) {
  ...
  PRINTF("something");
  ...
}

vs.

#ifdef DEBUG
  #define PRINTF(...) printf(__VA_ARGS__)
#endif

int main(void) {
  ...
  #ifdef DEBUG
    PRINTF("something");
  #endif
  ...
}

I'm not sure which technique I prefer. On one hand wrapping every PRINTF statement with #ifdef's would be ugly. On the other hand it would be nice to know at compile time if I've called a function that doesn't really work in the context.

I think the deciding factor will be whether or not having the (void)0 macros is going to affect the size of the executable.

When the code is compiled, what happens to the (void)0's? If PRINTF is defined as (void)0, does that mean the executable is going to contain some sort of (void)0 instruction or will it be completely ignored?


Solution

  • (void) 0;
    

    is an expression statement with no side-effect. Any sane implementation will optimize this statement out (what else an implementation could do with such a statement?).

    Having (void) 0 as a macro definition is endorsed by the C Standard as it appears in (C11) 7.2p1 for assert macro definition if NDEBUG is defined:

    #define assert(ignore) ((void)0)
    

    Note that defining:

    #define PRINTF(...) (void)0
    

    instead of

    #define PRINTF(...)
    

    has an advantage. In the first case, you have an expression (like a function that returns no value) and so it is usable for example in a comma expression or in a conditional expression.

    For example:

    // Comma expression
    printf("test"), PRINTF("Hi Dennis");
    
    // Conditional expression
    test-expr ? perror("Hello") : PRINTF("world");
    

    This two expression statements are only valid with the former PRINTF definition (with (void) 0).