what is the difference between #if, #ifdef and #ifndef?

Started by
3 comments, last by samoth 7 years ago

Question in the title.

Thank you in advance.

Advertisement

This is not Google.

A quick search gave this as a result, which should contain all the information you need:

http://www.cplusplus.com/doc/tutorial/preprocessor/

Hello to all my stalkers.

What he said, but quickly:

#if is what you expect

#ifdef is equivalent to #if defined(...)

#ifndef is equivalent to #if !defined(...)

SlimDX | Ventspace Blog | Twitter | Diverse teams make better games. I am currently hiring capable C++ engine developers in Baltimore, MD.
#if checks symbol's value
#ifdef or #ifndef checks symbol's existence.


#if checks symbol's value
#ifdef or #ifndef checks symbol's existence.

While this is not wrong, I don't like leaving it there that simplistic. Because, unluckily, it is not that simple.

#ifdef checks whether a single identifier with the given name exists, that's right. It is mostly identical to #if defined(...), but it is not quite the same.

#if checks whether a (almost deliberately complex) constant expression evaluates to zero or not. This constant expression may, of course, contain a macro identifier, or it may contain one or several unary operation expressions such as defined(), possibly with boolean or arithmetic operators between them. One not-so-obvious thing about it is that macros get replaced prior to evaluating the expression, but after said macro replacement, all remaining keywords or identifiers except for true and false are replaced with the (literal) number zero.

Now why is this a problem? If you write #ifdef, then it is pretty much clear what your intention is, and it is pretty much clear that there can be only two possible outcomes. It doesn't look like it could do anything but exactly what you expect.

With #if, although it looks like things are pretty clear as well, that is not necessarily the case. The thing that most people will probably expect is that if you accidentially use an identifier that doesn't exist (maybe because you misspelled it) in an #if statement, you will get an error. That only makes sense, after all you're not just looking up whether some identifier exists, but you're evaluating an expression. How could an expression be evaluated if something is missing or spelled wrong! Clearly the compiler will warn you about this.

Unluckily, that's not how things work. Instead you get silent failure because the preprocessor replaces anything it doesn't know with zero and then removes the conditional block when you really didn't intend that to happen. You can even foolishly use a runtime identifier with #if (which of course cannot possibly work!) but still you will not get an error or the slightest warning. This applies to constexpr or enum identifiers as well (maybe much to the surprise of novice programmers!).The preprocessor will just silently strip away the conditional block.

This topic is closed to new replies.

Advertisement