4

When trying to debug my code, I marked a few printf with this:

#if debug
    printf(...);
#endif

And at the start of the file, I mistakenly wrote #define debug instead of #define debug 1

gcc threw the following error:

error: #if with no expression

Now I have 2 options:

  1. changing the define into #define debug 1
  2. changing the if into #ifdef debug

I know that upon seeing #define debug 1 the PP will replace each debug in my code to 1 and that's why #if debug in my code didn't work - the compiler sees no expression...

My question is, when I use #ifdef debug - what happens? I figure debug is saved somewhere and checked, but where and how?

CIsForCookies
  • 12,097
  • 11
  • 59
  • 124
  • 1
    The "where" could be as simple as a list of all macros in the current [translation unit](https://en.wikipedia.org/wiki/Translation_unit_(programming)), and the "how" (in regards to checking with `#ifdef`) is simply looking for the macro in the list. – Some programmer dude Jul 19 '17 at 08:09
  • How can I locate and print this macro list? – CIsForCookies Jul 19 '17 at 08:13
  • 1
    @CIsForCookies for `gcc`, [look here](https://stackoverflow.com/questions/2224334/gcc-dump-preprocessor-defines) (of course, instead of `/dev/null`, feed it your actual source file) –  Jul 19 '17 at 08:14
  • 1
    That depends on the compiler you're using. It might have options to give you that list. Or it might not have. – Some programmer dude Jul 19 '17 at 08:14

2 Answers2

6

It's actually quite simple: #define debug does define debug to be empty. It is still defined. An empty macro is different from one that doesn't exist. #undef debug would remove the macro.

#ifdef doesn't care about the value. It only checks whether the macro is defined to whatever. If you don't care about the value, always use #ifdef.

  • I'm trying to check it against __#define debug ""__ but that throws an error: token """" is not valid in preprocessor expressions – CIsForCookies Jul 19 '17 at 08:17
  • 1
    @CIsForCookies Don't confuse preprocessor syntax with C syntax. A preprocessor token can of course contain `""`, for the preprocessor, this are just two characters (it's NOT the same as *empty*). -- `#define debug ""` is perfectly valid. –  Jul 19 '17 at 08:21
  • So the only way to replace a string with empty string for the PP will be to leave it as I defined? – CIsForCookies Jul 19 '17 at 08:22
  • 2
    @CIsForCookies I don't understand what you're asking in this last comment. If you want your macro to expand to an *empty string constant*, define it as `""`. If you want your macro to be empty (so the expansion will contain nothing at all), define it without a value. –  Jul 19 '17 at 08:24
3

The relevant syntax for the #define preprocessing directive is spelled out in §6.10 ¶1 (C11 Draft Standard):

# define identifier replacement-list new-line
...
replacement-list: pp-tokensopt

The semantics of the #define directive are found in §6.10.3:

A preprocessing directive of the form

# define identifier replacement-list new-line

defines an object-like macro that causes each subsequent instance of the macro name to be replaced by the replacement list of preprocessing tokens that constitute the remainder of the directive. The replacement list is then rescanned for more macro names as specified below.

Note that a replacement-list is optionally composed of preprocessing tokens, and thus may be empty. So, to consider a footnoted example from the Standard:

#define EMPTY

Since, according to §6.10.3 ¶7:

The identifier immediately following the define is called the macro name. There is one name space for macro names.

the macro name EMPTY has been defined, and exists in the namespace for macro names. Each subsequent instance of EMPTY will be replaced by no preprocessing tokens.

ad absurdum
  • 19,498
  • 5
  • 37
  • 60