views:

553

answers:

8

In C/C++

What happens to code placed between an #if 0/#endif block?

#if 0

//Code goes here

#endif

Does the code simply get skipped and therefore does not get executed?

+13  A: 

It permanently comments out that code so the compiler will never compile it.

The coder can later change the #ifdef to have that code compile in the program if he wants to.

It's exactly like the code doesn't exist.

Nilbert
+22  A: 

Not only does it not get executed, it doesn't even get compiled.

#if is a preprocessor command, which gets evaluated before the actual compilation step. The code inside that block doesn't appear in the compiled binary.

It's often used for temporarily removing segments of code with the intention of turning them back on later.

David
...back on later, but is often forgoten and makes code horrible to read.
pmr
+19  A: 

It's identical to commenting out the block, except with one important difference: Nesting is not a problem. Consider this code:

foo();
bar(x, y); /* x must not be NULL */
baz();

If I want to comment it out, I might try:

/*
foo();
bar(x, y); /* x must not be NULL */
baz();
*/

Bzzt. Syntax error! Why? Because block comments do not nest, and so (as you can see from SO's syntax highlighting) the */ after the word "NULL" terminates the comment, making the baz call not commented out, and the */ after baz a syntax error. On the other hand:

#if 0
foo();
bar(x, y); /* x must not be NULL */
baz();
#endif

Works to comment out the entire thing. And the #if 0s will nest with each other, like so:

#if 0
pre_foo();
#if 0
foo();
bar(x, y); /* x must not be NULL */
baz();
#endif
quux();
#endif

Although of course this can get a bit confusing and become a maintenance headache if not commented properly.

Tyler McHenry
Just note that the code inside #if has to be lexically correct (as opposed to comments) and preprocessor directives are still in effect (ditto).
jpalecek
@jpalecek: What do you mean? The code within the `#if 0` `#endif` block is essentially skipped, it can be almost anything you want it to be without the compiler [or the preprocessor] caring.
Dennis Zickefoose
@dennis (re @jpaleck), `#if 0` `foo();` `this doesn't parse` `#endif` isnt lexically correct.
David X
@David: Its not lexically correct, but it will still compile. So the code doesn't have to be lexically correct.
Dennis Zickefoose
@Dennis, I get `foo.c:3: unterminated string or character constant` from gcc, what're you using?
David X
+5  A: 

When the preprocessor sees #if it checks whether the next token has a non-zero value. If it does, it keeps the code around for the compiler. If it doesn't, it gets rid of that code so the compiler never sees it.

If someone says #if 0 they are effectively commenting out the code so it will never be compiled. You can think of this the same as if they had put /* ... */ around it. It's not quite the same, but it has the same effect.

If you want to understand what happened in detail, you can often look. Many compilers will allow you to see the files after the preprocessor has run. For example, on Visual C++ the switch /P command will execute the preprocessor and put the results in a .i file.

Steve Rowe
Not quite. The preprocessor parses by line rather than by token. According to your explanation it would not be possible to say e.g. `#if WIN32 || __CYGWIN__` but this does work as expected.
Ben Voigt
I was simplifying. If there is an or, it will check whether either token is non-zero. Likewise if there is an and it will check whether both are non-zero.
Steve Rowe
+3  A: 

Lines beginning with a # are preprocessor directives. #if 0 [...] #endif blocks do not make it to the compiler and will generate no machine code.

You can demonstrate what happens with the preprocessor with a source file ifdef.cxx:

#if 0
This code will not be compiled
#else
int i = 0;
#endif

Running gcc -E ifdef.cxx will show you what gets compiled.

You may choose to use this mechanism to prevent a block of code being compiled during the development cycle, but you would probably not want to check it in to your source control as it just adds cruft to your code and reduces readability. If it's a historical piece of code that has been commented out, then it should be removed: source control contains the history, right?

Also, the answer may be the same for both C and C++ but there is no language called C/C++ and it's not a good habit to refer to such a language.

Johnsyweb
What's wrong with saying C/C++ as shorthand for "C or C++"? Do you honestly think that anyone is going to be confused into thinking that there is a language called "C/C++"?
Christopher Barber
@Chris: People constantly ask questions like "How do I do X in C/C++?" Which is a nonsensical question; you're coding in one or the other, and if you haven't chosen yet you should be explicit in that fact. So, yes, people are confused about there being a language called "C/C++"
Dennis Zickefoose
What a nonsensical statement! There are thousands of questions whose answers are relevant to both C and C++. Remember that this is a site for asking questions. Just because you are asking a general question doesn't mean you don't know what language you are using. If you suspect that is the case, as in this question, how does it help to specify C or C++? Do you think it would be helpful if every question that could apply to either C or C++ be asked twice?
Christopher Barber
@Christopher: You are right, there are many questions where the answers are just as relevant to C, C++ and Objective-C (this being one of them). Stack Overflow has a handy tagging system to denote to which languages a question belongs. As @Dennis mentions, SO (and other programming forums [fora?]) there are (too) many people who are confused as to the delineation between C and other C-derived languages who refer to these languages interchangeably as C/C++ making it harder to answer the question in the appropriate language.
Johnsyweb
A: 

Not quite

int main(void)
{
   #if 0
     the apostrophe ' causes a warning
   #endif
   return 0;
}

It shows "t.c:4:19: warning: missing terminating ' character" with gcc 4.2.4

Arthur Kalliokoski
This warning is generated by the preprocessor, not the compiler. The compiler only gets to see: # 1 "t.c"# 1 "<built-in>"# 1 "<command-line>"# 1 "t.c"int main(void){ return 0;}
Johnsyweb
+4  A: 
Jörg W Mittag
A: 

It is a cheap way to comment out, but I suspect that it could have debugging potential. For example, let's suppose you have a build that output values to a file. You might not want that in a final version so you can use the #if 0... #endif.

Also, I suspect a better way of doing it for debug purpose would be to do:

#ifdef DEBUG
// output to file
#endif

You can do something like that and it might make more sense and all you have to do is define DEBUG to see the results.

Daniel