Sign in to follow this  
LiziPizi

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

Recommended Posts


#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.

Edited by samoth

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this