user3817250
user3817250

Reputation: 1043

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?

Upvotes: 3

Views: 3186

Answers (3)

user3793679
user3793679

Reputation:

A half way decent compiler will optimise away dead (unreachable) code, so you can:

  #ifdef DEBUG
  #define PRINTF(...) if (1) { printf(__VA_ARGS__) ; }
  #else
  #define PRINTF(...) if (0) { printf(__VA_ARGS__) ; }
  #endif

which has the big advantage of allowing the compiler to check the debug code, no matter whether you are working with/without your DEBUG turned on -- which reduces the risk of ending up with painful teeth marks in your backside.

Upvotes: 2

ouah
ouah

Reputation: 145879

(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).

Upvotes: 8

Adam D. Ruppe
Adam D. Ruppe

Reputation: 25605

It'll be completely ignored, you can confirm this by looking at the assembly output (gcc -S will generate file.s, the asm output), compare with and without the (void)0 line and see that it is completely the same.

Upvotes: 5

Related Questions