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

  2. Edward Rutherford <> writes:
    > 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?


    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 (The_Other_Keith) <http://www.ghoti.net/~kst>
    Nokia
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Jun 9, 2011
    #2
    1. Advertising

  3. Keith Thompson wrote:

    > Edward Rutherford <> writes:
    >> 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?

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

    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. Edward Rutherford <> writes:
    > Keith Thompson wrote:
    >> Edward Rutherford <> writes:
    >>> 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?

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

    >
    > 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?


    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 (The_Other_Keith) <http://www.ghoti.net/~kst>
    Nokia
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Jun 10, 2011
    #4
  5. Edward Rutherford

    Shao Miller Guest

    On 6/11/2011 3:01 PM, Edward Rutherford wrote:
    > Keith Thompson wrote:
    >> ...
    >> 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
    >> ...

    >
    > Exactly right, Keith, except that your
    > #define COMMENT //
    > could never work because the // would be interpreted as a comment on the
    > macro line and get deleted, i.e. the line would be equivalent to
    > #define COMMENT
    >
    > I assume this is the reason for the futzing around with stringifying
    > two / characters in the macro from my original post.
    >
    > Your suggested functionlike macro may be the best available, but it's a
    > shame there's not a more elegant solution.


    "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

    On 9 Jun., 20:32, Edward Rutherford
    <> wrote:
    > 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, ...


    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. On Jun 9, 1:32 pm, Edward Rutherford
    <> wrote:
    > 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.


    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. On Jun 12, 2:34 am, Jens <> wrote:
    > 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.


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

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Dead RAM
    Replies:
    20
    Views:
    1,111
    John Harrison
    Jul 14, 2004
  2. D Senthil Kumar

    macro name from macro?

    D Senthil Kumar, Sep 20, 2003, in forum: C Programming
    Replies:
    1
    Views:
    580
    Jack Klein
    Sep 21, 2003
  3. sounak

    to get macro name from macro value

    sounak, Nov 22, 2005, in forum: C Programming
    Replies:
    17
    Views:
    501
    Mark McIntyre
    Nov 22, 2005
  4. Patrick Kowalzick
    Replies:
    5
    Views:
    470
    Patrick Kowalzick
    Mar 14, 2006
  5. Mike Manilone

    macro inside macro

    Mike Manilone, Oct 3, 2011, in forum: C Programming
    Replies:
    8
    Views:
    459
    Mike Manilone
    Oct 6, 2011
Loading...

Share This Page