Another macro question

Discussion in 'C Programming' started by Edward Rutherford, Jun 9, 2011.

  1. I am porting a codebase that makes extensive use of the following
    construction:

    #define CAT(a,b) a##b
    #define COMMENT CAT(/,/)
    COMMENT This is a comment

    It works as intended on the original Windows system, but not on the
    target compiler, which claims that comments should not be processed after
    macro expansion. So I have an odd situation where the preprocessor output
    is as intended and is compilable, whereas the original file is not.

    What is the truth, according to the standards? If it is invalid, can
    anyone suggest an alternative definition for the COMMENT macro that will
    achieve the same effect?

    Thanks.
     
    Edward Rutherford, Jun 9, 2011
    #1
    1. Advertisements

  2. The target compiler is correct. Comments are replaced by space
    characters in translation phase 3; macros invocations are expanded
    in phase 4 (C99 5.1.1.2). By the time the "//" is produced, it
    shouldn't be recognized as a comment delimiter.

    I don't believe there's any way for a macro to expand to a comment
    delimiter.

    Why not just use "//"?

    Or, if you must use "COMMENT" for some reason, modify your build
    procedure so each source file is filtered through something that
    replaces "COMMENT" by "//" (watch out for occurrences of "COMMENT"
    in string literals, header names, and, in principle, character
    constants).
     
    Keith Thompson, Jun 9, 2011
    #2
    1. Advertisements

  3. Keith.

    Rereading my original post I see that it may have been misleading as to
    how this macro is used.

    The idea is that it provides a way to selectively comment out individual
    lines of code: in effect, it is to single lines what
    #if DEBUGMODE...#endif is to blocks.

    So an example of a COMMENT line might be
    COMMENT logger_write(LOG_DEBUG2, "Entering foo function, x=%d", x);

    The COMMENT macro can either be defined as in my original post (to
    exclude the line), or as a null macro (to include the line).

    One possibility would be to look for all occurrences of COMMENT lines and
    surround them by #if...#endif blocks. However, this would clutter the
    code and make it much harder to read.

    Is there a portable, standards-compliant way to define COMMENT to achieve
    the desired effect?

    /EPR
     
    Edward Rutherford, Jun 10, 2011
    #3
  4. So you want something like

    #if DEBUGMODE
    #define COMMENT //
    #else
    #define COMMENT
    #endif

    (except that it actually works), right?

    I don't think you can *quite* do that. What you can do is:

    #if DEBUGMODE
    #define COMMENT(arg) arg
    #else
    #define COMMENT(arg)
    #endif

    Then your COMMENT line would have to look like:

    COMMENT(logger_write(LOG_DEBUG2, "Entering foo function, x=%d", x);)

    The semicolon inside the parentheses looks a bit funny, but the idea is
    that the argument to COMMENT is an arbitrary line of code, not an
    expression. You can probably get away with:

    COMMENT(logger_write(LOG_DEBUG2, "Entering foo function, x=%d", x));

    but that gives you an extra bare semicolon, which is ok in some contexts
    but not in others.

    Or you can make logger_write (and anything similar) a macro whose
    definition depends on DEBUGMODE (and consider calling it LOGGER_WRITE).
    Note that variadic macros are a new feature in C99; you might need to
    use something like:

    LOGGER_WRITE((LOG_DEBUG2, "Entering foo function, x=%d", x));

    so it takes exactly one argument.
     
    Keith Thompson, Jun 10, 2011
    #4
  5. Edward Rutherford

    Shao Miller Guest

    "So you want something like...except that it actually works...I don't
    think you can..."
    "except that your...could never work because..."

    It's nice to see agreement. :)
     
    Shao Miller, Jun 11, 2011
    #5
  6. Edward Rutherford

    Jens Guest

    As others have already mentioned this can't work with a complying
    compiler.

    But it is also not so productive, I think. This hides your code until
    the day you have to debug something so there are big chances that your
    code that you commented out didn't evolve in parallel with your other
    code. So generally it wouldn't compile anymore.

    A better solution is to put the debug code in something like

    #ifndef DEBUG_ME
    # define DEBUG_ME 0
    #endif

    if (DEBUG_ME) {
    // your code comes here
    }

    There, the debug code is checked at every compile but any decent
    compiler nowadays should completely ignore it afterwards. Then, the
    day you want to use this code you can compile with -DDEBUG_ME=1 and
    the code is executed.
     
    Jens, Jun 12, 2011
    #6
  7. What about doing an extra pre-process step?
    % cc -E source_with_COMMENT.c > source_without_COMMENT.c
    % cc source_without_COMMENT.c
     
    luser- -droog, Jun 13, 2011
    #7
  8. It's also straightforward to change from a compile-time option to a
    run-time option by changing DEBUG_ME to a variable. You lose the
    optimize-away-when-not-in-use feature, but it greatly increases your
    flexibility. Maybe you don't need the debugging output during
    initialization, but you need a trace from the main loop....
     
    luser- -droog, Jun 13, 2011
    #8
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.