[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.c

Another macro question

Edward Rutherford

6/9/2011 6:33:00 PM

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

Keith Thompson

6/9/2011 7:15:00 PM

0

Edward Rutherford <edward.p.rutherford79@REMOVETHIS.gmail.com> 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) kst-u@mib.org <http://www.ghoti.ne...
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

Edward Rutherford

6/10/2011 8:35:00 PM

0

Keith Thompson wrote:

> Edward Rutherford <edward.p.rutherford79@REMOVETHIS.gmail.com> 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

Keith Thompson

6/10/2011 9:22:00 PM

0

Edward Rutherford <edward.p.rutherford79@REMOVETHIS.gmail.com> writes:
> Keith Thompson wrote:
>> Edward Rutherford <edward.p.rutherford79@REMOVETHIS.gmail.com> 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) kst-u@mib.org <http://www.ghoti.ne...
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

Edward Rutherford

6/11/2011 8:01:00 PM

0

Keith Thompson wrote:

> Edward Rutherford <edward.p.rutherford79@REMOVETHIS.gmail.com> writes:
>> Keith Thompson wrote:
>>> Edward Rutherford <edward.p.rutherford79@REMOVETHIS.gmail.com> 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.

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.

/EPR

Shao Miller

6/11/2011 10:07:00 PM

0

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

Keith Thompson

6/11/2011 10:44:00 PM

0

Shao Miller <sha0.miller@gmail.com> writes:
> 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. :)

Yes, but I hadn't actually taken the time to realize that the //
in the macro definition would introduce a comment. I knew it
wouldn't result in a comment delimiter in the macro expansion,
but I didn't think beyond that.

--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.ne...
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

Jens

6/12/2011 7:34:00 AM

0

On 9 Jun., 20:32, Edward Rutherford
<edward.p.rutherfor...@REMOVETHIS.gmail.com> 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.

luserXtrog

6/12/2011 11:38:00 PM

0

On Jun 9, 1:32 pm, Edward Rutherford
<edward.p.rutherfor...@REMOVETHIS.gmail.com> 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

luserXtrog

6/12/2011 11:47:00 PM

0

On Jun 12, 2:34 am, Jens <jens.gust...@gmail.com> 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....