Is #ifdef MACRO equivalent to a comment
Asked Answered
S

8

8

Assuming that MACRO is not defined, are these equivalent

#ifdef MACRO
    Not valid C or C++ code
#endif

/*
    Not valid C or C++ code
*/

In GCC 4.7.1, it seems to be equivalent but are there preprocessors that do more?

Spit answered 14/6, 2013 at 8:47 Comment(1)
if MACRO is not defined then YES, code will not compile in both case, preprocessors are use for conditional compilation, if defined true then code compiles else notSubroutine
B
13

It depends on what you mean by "not valid C or C++ code".

Text inside a comment does not have to conform to most of the rules of the language. It isn’t even tokenized. This is perfectly valid:

/* This comment doesn't contain a valid sequence of preprocessing tokens
   (because of the apostrophe).  */

The only rules it does have to obey are the ones that control where the comment ends. People regularly get tripped up by backslash-newline in line comments (in fact, SO's syntax highlighter used to get this wrong!)

// Line comment with ascii art ending with a \
   Oops! This line is commented out too!

and less often (if only because every C tutorial warns you about this) by block comments not nesting:

/* you can't nest /* block comments */ these words are not commented */

On the other hand, text inside a "skipped" preprocessor conditional "group" does have to conform to some of the rules of the language. The exact words of the standard (C99 §6.10.1p5) are

Each directive’s condition is checked in order. If it evaluates to false (zero), the group that it controls is skipped: directives are processed only through the name that determines the directive in order to keep track of the level of nested conditionals; the rest of the directives’ preprocessing tokens are ignored, as are the other preprocessing tokens in the group.

There are two important bits. First, the text is tokenized, so it does have to be a valid sequence of preprocessing tokens.

#if 0
This skipped conditional group doesn't contain a valid sequence of
preprocessing tokens (because of the apostrophe).
#endif

is a syntax error.

$ gcc -fsyntax-only test.c
test.c:2:37: warning: missing terminating ' character
 this skipped conditional group doesn't contain a valid sequence of
                                     ^

Second, directives are still partially processed "in order to keep track of the level of nested conditionals", which means you can do this:

#if 0 // forget this entire mess
    #ifdef __linux__
    do_linux_specific_thing();
    #elif defined __APPLE__
    do_osx_specific_thing();
    #elif defined _WIN32
    do_windows_specific_thing();
    #endif
#endif

and you can’t do this:

    #ifdef __linux__
    do_linux_specific_thing();
    #elif defined __APPLE__
    do_osx_specific_thing();
#if 0 // forget windows
    #elif defined _WIN32
    do_windows_specific_thing();
    #endif
#endif

(You won’t get an error for that last, but…

$ gcc -E -P -U__linux__ -D__APPLE__ -D_WIN32 test.c
    do_osx_specific_thing();
    do_windows_specific_thing();

… I don’t think that’s what whoever wrote it meant it to do.)


Many guides to the language tell you to use #if 0 to "comment out" large regions of code that you want to disable temporarily. They say this because block comments don‘t nest. If you try to disable a region of code with a block comment, but there’s a block comment inside that region, the commenting-out will end prematurely and probably the code will fail to compile. This was more important in the days when C didn’t have line comments; some projects use only line comments for commentary, reserving block comments for disabling code.

But because code inside #if 0#endif is still tokenized, and nested preprocessor conditionals must still balance, you do have to be a little careful about where you put the #if 0 and the #endif. It’s usually not a problem, because the code used to compile before you disabled it, so it shouldn’t have anything in it to cause a tokenization error.

Brendon answered 10/2, 2017 at 13:57 Comment(0)
T
7

In the general case, both are equivalent.

However, if your "not valid C or C++ code" contains comments, the first form will work, whereas the second won't. That's because C standard forbids imbricated comments.

 /* Comments /* inside */ comments are not allowed. */

BTW, #if 0 is often prefered to #ifdef MACRO in that case.

#if 0
    Invalid C source code
#endif

See this question.

Titanesque answered 14/6, 2013 at 8:50 Comment(5)
Comments are for commenting, macros are for preprocessing-time options. There should be a valid C code inside such macros. at least, valid in certain circumstances. unmatched /* should not be there at all, #ifed out ot not.Hysterotomy
and, if you are worried about unmatched /*, then you should be worried about #endifs in the middle of the "invalid C source code".Hysterotomy
Wow, I had to actually go look up imbricate. That doesn't happen very often :-)Disperse
The MACRO way gives me a possibility to check if the block is interesting to me. Actually I will __MACRO__ to get into reserved namespace.Spit
@Elazar: #ifdef/#endif directives can be imbricated, but comments cannot. I am not refering to "unmatched /*, since it doesn't work with matched /* neither.Titanesque
N
5

Yes, they are equivalent, the preprocessing stage will eliminate Not valid C or C++ code before the compiler proper sees the code.

Preprocessing involves the removal of comments, and code that is #ifed out.

But if someone compiles the code with -DMACRO, the #ifdef version gets you in trouble, better use #if 0 to remove code via the preprocessor.

Ne answered 14/6, 2013 at 8:50 Comment(0)
D
1

The relevant part of the standard is C11 6.10.1 Conditional inclusion /6:

Each directive’s condition is checked in order. If it evaluates to false (zero), the group that it controls is skipped.

That means, if any of the various forms (if, ifdef and so on) evaluate to false, no processing of the group is done and it is totally removed in terms of later stages of processing. It does not get turned into a comment.

Disperse answered 14/6, 2013 at 8:55 Comment(0)
S
0

No, in your final code, there won't be any trace of the code inside the #ifdef:

// before
#ifdef MACRO
    Not valid C or C++ code
#endif
// after

After precompilations:

// before
// after

There's no remaining code in there.

Sender answered 14/6, 2013 at 8:52 Comment(6)
There will also be no code in the comment, so I would say yes they are both equal; both emptyHiccup
It is equivalent but not equal. OP is wrong believing that the code will be placed in a comment section. What's really happening is, the code is completely stripped.Sender
You won't even have the // before and // after comments remaining, because comments are stripped out before the preprocessing phase.Pacifist
Actually this is not true. Comments get removed by the preprocessor, too.Tui
@Pacifist You mean before the preprocessing directives phase, i.e. before processing macros and #ifs. But both phases are considered part of the preprocessor.Tui
@Tui Thank you for the correction. That is indeed what I meant (sorry...)Pacifist
H
0

If MACRO is not defined they should be equivalent. A typical way of commenting out large chunks of code is usually:

#if 0
code(); /* possibly with comments. */
#endif

This allows you to disable large parts of code even when they contain comments. So it's better than normal comments for disabling parts of code.

There's a caveat though. I've run into a compiler that choked on something like this:

#ifdef __GNUC__
#nonstandardpreprocessordirective
#endif

Where "nonstandardpreprocessordirective" was a preprocessor directive that only works on GCC. I'm not exactly sure what the standard says about this, but it has caused problems in reality in the past. I do not remember which compiler though.

Hornback answered 14/6, 2013 at 9:2 Comment(0)
H
0

They are close, but not completely. assuming MACRO is not defined (or assuming you are using #if 0 as recommended in other answers here):

#ifdef MACRO
Not valid C or C++ code
*/  - does no harm
#endif  - oops
more invalid code
#endif

and comments:

/*
    Not valid C or C++ code
    #endif - does no harm
    */ - oops
*/

Comments are for commenting, #ifdef are for disabling legal code. Aarbitrary text should not reside in the source at all.

Hysterotomy answered 14/6, 2013 at 9:4 Comment(0)
D
0

Yes, most pre-processors (if not all) will remove both, comments and directives evaluated to 0. The differences between the two are mostly functional.

My advice is to use directives to "comment" code (#if 0 {} #endif) and use comments just for commenting (quite logic right?). Main reasons are:

  • Directives can be activated/deactivated just modifying 1 line in the code. Block comments require insertion/deletion of 2 elements in different lines of the code.
  • Directives can be nested preserving the IF logic and can also contain block comments. /Block comments/ cannot be nested and this can be problematic when you comment big pieces of code which can contain another comments.
#if 0
...
#if 1
#endif
...
#endif
  • Simple #if 0 directives can be easily converted in define or eval directives which allow a more dynamic conditional code processing.
//Classic verbose code line comment

#if 0
//Directive verbose line or block comment   
#endif

#define verbose 0
#if verbose
//Convenient eval directive to turn on/off this and other verbose blocks
#endif
  • Most IDEs do not highlight syntax of comment blocks but DO highlight syntax of directive code. Same happens with other features like indentation or autocompletion. This makes the readability of /**/ blocks quite poor in contrast to the #if 0 #endif blocks. Also the edition of commented code (e.g. adding a line or fixing something) is easier with directives.
Decarbonate answered 21/9, 2015 at 9:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.