• Create Account

Banner advertising on our site currently available from just \$5!

# Is this commenting macro safe to use?

Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

9 replies to this topic

### #1Sunsharior  Members   -  Reputation: 768

Like
0Likes
Like

Posted 22 May 2014 - 10:18 PM

Hello everyone.

I'm using a simple macro to comment out part of my code in release build, but i'm wondering if this could lead to some sort of problem, as i'm trying to cheat the precompiller into adding comments against the rule.

I use this to avoid writing duplicated code.

Basically, here is the macro

#if defined DEBUG
#define MACRO
#else
#define MACRO );/ ## /
#endif


What it does is: If i'm in debug build, it does nothing. If i'm in release build, it close a function and comment the rest of the line.

The "/ ## /" part is needed to trick the compiler into thinking comment dont exist. But they do.

This is how i use the macro. (The code is simplified)

//Initialize a long list of interfaced classes into a map, allowing easy Factory access.
void Bar()
{
//Assume each different letters is an interfaced class
Foo(A0, A1 MACRO, A2, A3, A4);
Foo(B0, B1 MACRO, B2, B3, B4);
// Many Foo later...
Foo(Z0, Z1 MACRO, Z2, Z3, Z4);
}

#if defined DEBUG
//Types don't really matter. Just the number of parameters is interesting.
void Foo(Type0, Type1, Type2, Type3, Type4)
{
// Do something, in debug
}
#else
void Foo(Type0, Type1)
{
// Do something, in release
}
#endif



As you can see, in release build, the compiler will see "Foo(A0, A1 );" as the comment will clear the rest of the line.
This way, i avoid writing this code:

#if defined DEBUG
Foo(A0, A1, A2, A3, A4);
Foo(B0, B1, B2, B3, B4);
// Many Foo later...
Foo(Z0, Z1, Z2, Z3, Z4);
#else
Foo(A0, A1);
Foo(B0, B1);
// Many Foo later...
Foo(Z0, Z1);
#endif


The reason i use it is to avoir writing duplicate code to avoid possible Copy/Paste errors.

As of writing this post, the macro work fine in either build, but i have this strange feeling i'm doing something cringe-worthy.

Am i really going overboard just to avoid writing duplicated code?

If so, is there other options?

Edited by Sunsharior, 22 May 2014 - 10:26 PM.

### #2Promit  Moderators   -  Reputation: 9451

Like
6Likes
Like

Posted 22 May 2014 - 11:32 PM

It might be safe, but it's certainly horrifying. At the very least I would use a macro that calls Foo, and change the definition of that macro based on DEBUG or not. Something like:

#ifdef DEBUG
#define CALL_FOO(a, b, c, d, e) Foo(a, b, c, d, e)
#else
#define CALL_FOO(a, b, c, d, e) Foo(a, b)
#endif

But I would revisit why you're doing this in the first place and think if maybe there's something you can do with the implementation of Foo itself. Or your overall code. Not really enough info to work with....

### #3Hodgman  Moderators   -  Reputation: 37954

Like
5Likes
Like

Posted 23 May 2014 - 12:13 AM

I do it this ugly way:

#ifdef _DEBUG
#define DEBUG(a) a
#else
#define DEBUG(a)
#endif

#define COMMA ,
...
Foo(A0, A1 DEBUG(COMMA A2 COMMA A3 COMMA A4));
Foo(B0, B1 DEBUG(COMMA B2 COMMA B3 COMMA B4));

### #4Strewya  Members   -  Reputation: 1799

Like
0Likes
Like

Posted 23 May 2014 - 07:45 AM

I must have some gaps in my knowledge, as i thought comments are removed before the precompiler processes the macros?

I know a macro like this wont work, because the compiler will see the two slashes as a comment and remove/ignore them:

#define MACRO //

But why/how does the one in the OP work?

#define MACRO / ## /

devstropo.blogspot.com - Random stuff about my gamedev hobby

### #5Servant of the Lord  Crossbones+   -  Reputation: 24015

Like
4Likes
Like

Posted 23 May 2014 - 08:18 AM

I do it this ugly way:

Foo(A0, A1 DEBUG(COMMA A2 COMMA A3 COMMA A4));
Foo(B0, B1 DEBUG(COMMA B2 COMMA B3 COMMA B4));

#define DEBUG_ARGS(...) , __VA_ARGS__

Foo(A0, A1, DEBUG_ARGS(A2, A3, A4));

This is GCC/MinGW, but it's standardized in C++11 now.

But why/how does the one in the OP work?
#define MACRO / ## /

## takes two characters and combine them. It takes / and / and turns it into //.

By the way, I agree that passing arguments only while debugging is sometimes suspect and should warrant a second glance at what you are doing.

Edited by Servant of the Lord, 23 May 2014 - 08:28 AM.

It's perfectly fine to abbreviate my username to 'Servant' rather than copy+pasting it all the time.
All glory be to the Man at the right hand... On David's throne the King will reign, and the Government will rest upon His shoulders. All the earth will see the salvation of God.
Of Stranger Flames -

[Need web hosting? I personally like A Small Orange]

### #6Lactose!  GDNet+   -  Reputation: 4837

Like
0Likes
Like

Posted 23 May 2014 - 08:19 AM

## takes two characters and combine them. It takes / and / and turns it into //.

Also known as token concatenation.

Project journal, check it out!

http://www.gamedev.net/blog/1830-lactoses-journal/

Hello to all my stalkers.

### #7Sunsharior  Members   -  Reputation: 768

Like
0Likes
Like

Posted 23 May 2014 - 08:22 AM

But why/how does the one in the OP work?

#define MACRO / ## /

This uses the concatenation operator "##" to insert a comment "//"

Edit: beaten by servant of the lord.

Edited by Sunsharior, 23 May 2014 - 08:26 AM.

### #8Bacterius  Crossbones+   -  Reputation: 10560

Like
2Likes
Like

Posted 23 May 2014 - 08:33 AM

Keep in mind that using token pasting to synthesize a comment is not actually allowed by the standard, as it explicitly states comment removal occurs before macro processing - many compilers do it after, or both before and after, but some (like gcc) will outright reject the macro as it would expand to an illegal token after the macro processing phase:

error: pasting "/" and "/" does not give a valid preprocessing token


I would be very wary of using that macro on an unknown compiler, there is no telling what it would actually do.

The slowsort algorithm is a perfect illustration of the multiply and surrender paradigm, which is perhaps the single most important paradigm in the development of reluctant algorithms. The basic multiply and surrender strategy consists in replacing the problem at hand by two or more subproblems, each slightly simpler than the original, and continue multiplying subproblems and subsubproblems recursively in this fashion as long as possible. At some point the subproblems will all become so simple that their solution can no longer be postponed, and we will have to surrender. Experience shows that, in most cases, by the time this point is reached the total work will be substantially higher than what could have been wasted by a more direct approach.

- Pessimal Algorithms and Simplexity Analysis

### #9Sunsharior  Members   -  Reputation: 768

Like
0Likes
Like

Posted 23 May 2014 - 08:43 AM

As many already stated, i will revise the logic of my code to avoid using preprossesor-comments altogether. I already have an idea on how i might do that cleanly.

I understand now, the macro is not standard and should be avoided.

Thank you everyone.

### #10Strewya  Members   -  Reputation: 1799

Like
0Likes
Like

Posted 23 May 2014 - 08:44 AM

Yes, i do realize token pasting is occuring, the question was more in line with "why are comments allowed to exist after the macro processing", since afaik they are removed before it.

Bacterius' answer is what i was after, thanks!

devstropo.blogspot.com - Random stuff about my gamedev hobby

Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

PARTNERS