4

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?

9
  • 2
    (void)0 will likely not generate any code. Commented Jul 29, 2014 at 17:08
  • If you have doubts, why don't you simply leave it out, I mean, the definition? You could really just write the #else definition as #define PRINTF(...) alone, and your lines would (hope I'm right here) simply be ;s, i.e. empty-statements. Commented Jul 29, 2014 at 17:15
  • What's wrong with #define PRINTF(...) (you define a macro replacement as the empty string) Commented Jul 29, 2014 at 17:15
  • 1
    Why do you ask a question that can only be answered for a specific compiler without saying at any time what your compiler is? Commented Jul 29, 2014 at 17:23
  • 1
    @PascalCuoq I assumed the treatment of (void)0 would be standard across c compilers. I'm using the Code Composer Studio IDE that keeps me somewhat in the dark about what compiler I'm using. Commented Jul 29, 2014 at 17:38

3 Answers 3

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

Sign up to request clarification or add additional context in comments.

Comments

5

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.

2 Comments

Is it the preprocessor or the compiler that completely ignores it?
Neither really, I guess I should have used different wording: the preprocessor leaves in the (void)0 and the compiler sees it (try to assign it to a variable, for example, and gcc will complain that you didn't ignore a void value like you are supposed to) but it doesn't actually generate any code because it is a do-nothing expression. So it is ignored in terms of code generation, the preprocessor and compiler front end both see it.
2

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.

6 Comments

It is a great advantage but note that it also changes the semantic, PRINTF is no longer a substitution for expression but now is a statement (so can no longer be used where an expression can be used).
@ouah in this case, PRINTF can't be used in an expression anyway, due to it possibly having the void type.
Why if (0) instead of just nothing? The compiler may remove this, but still...
@DrewMcGowen see my answer in OP question, void expression can be used as operands of comma expression or conditional expression.
OK... well the if could be replaced by an (1 ? printf(..) : (void)0) ?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.