62

Suppose the "empty" macro definition

#define FOO

Is it valid Standard C? If so, what is FOO after this definition?

moooeeeep
  • 31,622
  • 22
  • 98
  • 187
  • 3
    It is empty string, and yes, it is acceptable. – nhahtdh Dec 15 '12 at 12:30
  • 2
    Just to point out, [here's](http://stackoverflow.com/q/8592056/557306) another question which involves an interesting use of empty defines. – sidyll Dec 15 '12 at 12:40

3 Answers3

70

It is simply a macro that expands to, well, nothing. However, now that the macro has been defined you can check with #if defined (or #ifdef) whether it has been defined.

#define FOO

int main(){
    FOO FOO FOO
    printf("Hello world");
}

will expand to

int main(){

    printf("Hello world");
}

There are certain situations where this comes in very handy, for example additional debug information, which you don't want to show in your release version:

/* Defined only during debug compilations: */
#define CONFIG_USE_DEBUG_MESSAGES

#ifdef CONFIG_USE_DEBUG_MESSAGES
#define DEBUG_MSG(x) print(x)
#else
#define DEBUG_MSG(x) do {} while(0)
#endif

int main(){
    DEBUG_MSG("Entering main");
    /* ... */
}

Since the macro CONFIG_USE_DEBUG_MESSAGES has been defined, DEBUG_MSG(x) will expand to print(x) and you will get Entering main. If you remove the #define, DEBUG_MSG(x) expands to an empty do-while loop and you won't see the message.

Zeta
  • 103,620
  • 13
  • 194
  • 236
  • 3
    This is very risky, since it can break compilation esp. when you have statements like ```if (x) DEBUG_MSG("test"); else DEBUG_MSG("test");```. I prefer to declare my empty macro with an no-effect statement like ```#define DEBUG_MSG(x) do {} while(0)``` – Ely Feb 24 '17 at 08:55
  • 3
    @Ely Why would that break? If `DEBUG_MSG` was defined as `#defined DEBUG_MSG(x)` then `else DEBUG_MSG("test")` just becomes `else ;` which is valid because `;` is the 'empty statement'. – Pharap May 05 '18 at 23:43
  • I sometimes do something like that: `#define NOTHING` Then stuff like `int NOTHING main()` –  Jul 17 '19 at 21:58
  • 1
    @Ely Why would that break? Why not just `{}`? – endolith Aug 27 '21 at 18:57
  • But in the real world, Log functions have variadic parameters `DEBUG_MSG("message %s %s %s", parameters, and, more);`. It is still compatible with such syntax, or do we have to take care or the parameters which have to be wiped with the function on Release mode? – Sandburg May 18 '22 at 08:17
  • @Sandburg it's compatible, and the same holds, e.g. you can use `#define DEBUG_MSG(fmt, ...)` and keep the definition empty. – Zeta May 21 '22 at 11:52
22

Yes, empty define is allowed by the standard.

C11 (n1570), § 6.10 Preprocessing directives

control-line:
   # define identifier replacement-list new-line
   # define identifier lparen identifier-list(opt) ) replacement-list new-line
   # define identifier lparen ... ) replacement-list new-line
   # define identifier lparen identifier-list , ... ) replacement-list new-line
replacement-list:
    pp-tokens(opt)

A common utilisation is inclusion guards.

#ifndef F_H
# define F_H

#endif
md5
  • 23,373
  • 3
  • 44
  • 93
2

Empty macro definitions can also be used for self-documentation. The IN in the code snippet below is a sample. The code and the comment are both quoted from the EDK II project.

//
// Modifiers for Data Types used to self document code.
// This concept is borrowed for UEFI specification.
//

///
/// Datum is passed to the function.
///
#define IN


typedef
EFI_STATUS
(EFIAPI *EFI_BLOCK_RESET)(
  IN EFI_BLOCK_IO_PROTOCOL          *This,
  IN BOOLEAN                        ExtendedVerification
  );
smwikipedia
  • 61,609
  • 92
  • 309
  • 482
  • 2
    I would use another example. It doesn't have to be a quote from actual code, but the current example contains a rather large amount of unnecessary information. (By the way, make sure that your answer still answers the original question; it works well with the other answers, but as a standalone answer, it doesn't really fit the question "What does `FOO` expand to"?). – Zeta Aug 11 '15 at 14:14
  • Thanks for pointing it out. I just happen to be reading this piece of code when see this question. Since the answer has long been chosen, I just hope my reply can serve as some educative reference. – smwikipedia Aug 11 '15 at 14:48