By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,421 Members | 1,127 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,421 IT Pros & Developers. It's quick & easy.

Conditional code

P: n/a
Lets say you have a function "debug printf" which works like printf but will
get left out if _DEBUG flag is not defined along with the strings which are
to be printed.

Now I defined this:

#ifdef _DEBUG
void dbgprintf(char *szFormat, ...);
#else
#define dbgprintf
#endif

This works fine but under some compilers eg. gcc it will give me a huge
bunch of warnings saying the statement has no effect. This is ofcourse true,
but I don't need to be reminded since this was the intention. Does any of
you have good ideas how I can improve the macro to stop the compiler from
giving this?

Thanks in advance.
-- John
Jul 23 '05 #1
Share this Question
Share on Google+
16 Replies


P: n/a

"John Smith" <jo********@x-formation.com> wrote in message
news:42*********************@dread11.news.tele.dk. ..
Lets say you have a function "debug printf" which works like printf but will get left out if _DEBUG flag is not defined along with the strings which are to be printed.

Now I defined this:

#ifdef _DEBUG
Note that the above name is reserved for the implementation in ISO C++,
since it begins with an underscore and a capital letter. I guess this is ok
if you are making use of the compilers built-in debug flags, but I would
recommend against it. I always just define DEBUG or MY_DEBUG when I want to
do something like this example, and that works just fine.
void dbgprintf(char *szFormat, ...);
#else
#define dbgprintf
#endif

This works fine but under some compilers eg. gcc it will give me a huge
bunch of warnings saying the statement has no effect. This is ofcourse true, but I don't need to be reminded since this was the intention. Does any of
you have good ideas how I can improve the macro to stop the compiler from
giving this?


I don't understand why you would see more than one error message ... are you
using include guards on your headers (I assume the above appears in exactly
one header file somewhere in your program.

In any case, why not just write:
// ...
#else
#define dbgprintf /**/

or something like that?

HTH,

Dave Moore
Jul 23 '05 #2

P: n/a
"John Smith" <jo********@x-formation.com> wrote in message
news:42*********************@dread11.news.tele.dk. ..
Lets say you have a function "debug printf" which works like printf but will get left out if _DEBUG flag is not defined along with the strings which are to be printed.

Now I defined this:

#ifdef _DEBUG
void dbgprintf(char *szFormat, ...);
#else
#define dbgprintf
#endif


1. You could use in your code

dbgprintf("Print this string");

and define

#ifdef _DEBUG
void dbgprintf(whatever_arguments ...)
{
printf(...
}
#else // #ifdef _DEBUG
void dbgprintf(whatever_arguments ...)
{
// Do nothing.
}
#endif // #ifdef _DEBUG

2. Personally, I'm apprehensive about this approach at all. Consider the
following
dbgprintf("%d", my_terribly_expensive_operation());
or
dbgprintf("%d", my_operation_with_various_side_effects());

Then the compiler would call my_terribly_expensive_operation() or
my_operation_with_various_side_effects() even in release mode - probably not
what I want.
So I usually define dbgprintf as a macro itsel - this way the compiler can
eleminate its arguments completely.

3. Another matter which is possibly personal taste - it might be better to
distinguish between debug and trace: the first checks internal invariants;
the second outputs diagnostic information. Personally, I think these should
be orthogonal. There are cases where I find bugs in release mode only (e.g.,
because of thread races, which debug mode can change entirely). At the very
least, I usually try to have orthogonal debug and trace macros.
Jul 23 '05 #3

P: n/a
John Smith wrote:

This works fine but under some compilers eg. gcc it will give me a huge
bunch of warnings saying the statement has no effect.


Turn off the warning. You know better than some anonymous compiler
writer whether your code does what you meant it to do.

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)
Jul 23 '05 #4

P: n/a
> Note that the above name is reserved for the implementation in ISO C++,
since it begins with an underscore and a capital letter. I guess this is ok if you are making use of the compilers built-in debug flags, but I would
recommend against it. I always just define DEBUG or MY_DEBUG when I want to do something like this example, and that works just fine.
Actually it's from Microsoft Compilers which sets that symbol. I just reused
it. The only thing I can say is that if people will have problems with it in
future, I won't be the only one.

I don't understand why you would see more than one error message ... are you using include guards on your headers (I assume the above appears in exactly one header file somewhere in your program.

Yes I have include guards. I'm sorry I wasn't telling the whole story. The
reason for having multiple warnings is just because I call dbgprintf()
multiple times in my code.
In any case, why not just write:
// ...
#else
#define dbgprintf /**/

or something like that?


Well I do that... and it works. But thats what gives warnings.
Assume we use it:

....
dbgprintf("test\n");

after the macro expansion it will look like:

("test\n");

and thus the code is not doing anything meaningful and I get the warning.

-- John
Jul 23 '05 #5

P: n/a
John Smith wrote:
Lets say you have a function "debug printf" which works like printf but will
get left out if _DEBUG flag is not defined along with the strings which are
to be printed.

Now I defined this:

#ifdef _DEBUG
void dbgprintf(char *szFormat, ...);
#else
#define dbgprintf
#endif

This works fine but under some compilers eg. gcc it will give me a huge
bunch of warnings saying the statement has no effect. This is ofcourse true,
but I don't need to be reminded since this was the intention. Does any of
you have good ideas how I can improve the macro to stop the compiler from
giving this?
...


I hope you understand that when '_DEBUG' is not defined the statement

dbgprintf("%d %d %d", a, b, c);

turns (after preprocessing) into

("%d %d %d", a, b, c);

i.e. it is not completely left out. This is a completely different
statement with completely different semantics. In many cases it will
have no effect (which is what the compiler is trying to tell you), but
is it actually what you wanted to do?

--
Best regards,
Andrey Tarasevich
Jul 23 '05 #6

P: n/a
> I hope you understand that when '_DEBUG' is not defined the statement

dbgprintf("%d %d %d", a, b, c);

turns (after preprocessing) into

("%d %d %d", a, b, c);

i.e. it is not completely left out. This is a completely different
statement with completely different semantics. In many cases it will
have no effect (which is what the compiler is trying to tell you), but
is it actually what you wanted to do?


Actually yes it is. I'd rather get it removed all together. The idea is to
print out when in debug mode and leave the code out in release mode
(including the string to print).
Another guy suggested to make a dummy function which does nothing but it's
not suitable to me since the strings are still left in.

if the function had known arguments I could just make a dummy like:
#define dbgprintf(a,b,c)

but since it uses varargs I'm not sure how to create such a macro which
satisfies it.

The alternative would be like manually declare each line:

#ifdef _DEBUG
printf("we are in debug mode now\n");
#endif

But this takes 3 lines of code whereas dbgprintf() only takes 1.

Any ideas?

Thanks.
-- John
Jul 23 '05 #7

P: n/a
In any case, why not just write:
// ...
#else
#define dbgprintf /**/

or something like that?


Well I do that... and it works. But thats what gives warnings.
Assume we use it:

...
dbgprintf("test\n");

after the macro expansion it will look like:

("test\n");


ROFL .. I was wondering what on earth you were talking about until I looked
closely at my earlier suggestion .. what I meant was:

#else
#define dbgprintf //

that way whatever the args of dbgprintf are, they will be turned into a
comment. I knew I had used comments previously to deal with this, but I
didn't remember exactly how. Sorry for the confusion.

HTH,

Dave Moore
Jul 23 '05 #8

P: n/a
John Smith wrote:
I hope you understand that when '_DEBUG' is not defined the statement

dbgprintf("%d %d %d", a, b, c);

turns (after preprocessing) into

("%d %d %d", a, b, c);

i.e. it is not completely left out. This is a completely different
statement with completely different semantics. In many cases it will
have no effect (which is what the compiler is trying to tell you), but
is it actually what you wanted to do?


Actually yes it is. I'd rather get it removed all together. The idea is to
print out when in debug mode and leave the code out in release mode
(including the string to print).


There is another rather well-known approach. Define your macro as

#ifdef _DEBUG
void dbgprintf_(char *szFormat, ...);
#define dbgprintf(p) dbgprintf_ p
#else
#define dbgprintf(p)
#endif

and use it as follows

dbgprintf(("%d %d %d\n", a, b, c));

(note the double parenthesis). In this case everything will be left out
in non-debug version, but you have to use '(())', which makes it look a
little inelegant.

--
Best regards,
Andrey Tarasevich
Jul 23 '05 #9

P: n/a
Dave Moore wrote:

ROFL .. I was wondering what on earth you were talking about until I looked
closely at my earlier suggestion .. what I meant was:

#else
#define dbgprintf //

that way whatever the args of dbgprintf are, they will be turned into a
comment. I knew I had used comments previously to deal with this, but I
didn't remember exactly how. Sorry for the confusion.
...


This might work with some compilers, but won't work in general. In C++
the comments are fully processed (and replaced with whitespace) before
the preprocessor has a chance to do its thing. The compiler is free to
assume that preprocessor doesn't generate any new comments.

--
Best regards,
Andrey Tarasevich
Jul 23 '05 #10

P: n/a
> ROFL .. I was wondering what on earth you were talking about until I
looked
closely at my earlier suggestion .. what I meant was:

#else
#define dbgprintf //


Good idea but unfortunatly gcc wasn't fooled by it. It just ignores the
comment and continues with the warnings.
Too bad.

-- John
Jul 23 '05 #11

P: n/a
>
Turn off the warning. You know better than some anonymous compiler
writer whether your code does what you meant it to do.

Yes that will be my last way out if I don't find a better way. As suggested
in other threads the codes isn't removed completely so theres still room for
alternate improvements.

Unfortunatly gcc doesn't spit out error codes like some other compilers
does, so it's a little harder to be sure you turn off a specific warning
message.

-- John
Jul 23 '05 #12

P: n/a
"John Smith" <jo********@x-formation.com> wrote in message
news:42*********************@dread11.news.tele.dk. ..
ROFL .. I was wondering what on earth you were talking about until I

looked
closely at my earlier suggestion .. what I meant was:

#else
#define dbgprintf //


Good idea but unfortunatly gcc wasn't fooled by it. It just ignores the
comment and continues with the warnings.
Too bad.


Herb Sutter explains the reason at the end of the following article:

http://www.gotw.ca/gotw/077.htm

Ali

Jul 23 '05 #13

P: n/a
"Dave Moore" <dt*****@email.unc.edu> schrieb im Newsbeitrag news:36*************@individual.net...
#define dbgprintf //

that way whatever the args of dbgprintf are, they will be turned into a
comment.


Not a good idea. Even if it would work, it would only work with single line statements. Something like

dbgprintf("....",
arg1,
arg2,
//...
);

would most likely cause a compilation error.

Heinz
Jul 23 '05 #14

P: n/a

"Heinz Ozwirk" <ho**********@arcor.de> wrote in message
news:42***********************@newsread4.arcor-online.net...
"Dave Moore" <dt*****@email.unc.edu> schrieb im Newsbeitrag
news:36*************@individual.net...
#define dbgprintf //

that way whatever the args of dbgprintf are, they will be turned into a
comment.


Not a good idea. Even if it would work, it would only work with single line
statements. Something like

dbgprintf("....",
arg1,
arg2,
//...
);

would most likely cause a compilation error.

Heinz

Well .. I never used my homemade debug utility that way so it never came up
.... what worries me more is that now it doesn't work properly anymore, at
least not on g++. I can't remember for sure what platform I initially used
the trick on (Metrowerks I think). Bummer ... I liked it because it was so
simple and didn't rely on any "macro magic", which I find frightening. I
guess I will have to implement one of the other strategies posted here if I
have a need for such a "trick" again in the future.

Thanks for straightening me out y'all.

Dave Moore
Jul 23 '05 #15

P: n/a
What about this version:

#ifdef _DEBUG
statid void debugprintf_(const char *, ...) {}
#define debugprintf debugprintf_
#endif

So in debug mode all calls to debugprintf will be translated to
debugprintf_, and that function then does nothing.

This method has the advantage/disadvantage that all the arguments to
debugprintf will always be evaluated. This is good because it saves you
from error caused by missing side effects of arguments no evaluated in
the release version, but is also bad because you waste cpu time in the
release mode.

harald

Jul 23 '05 #16

P: n/a
John Smith wrote:
Lets say you have a function "debug printf" which works like printf but
will get left out if _DEBUG flag is not defined along with the strings
which are to be printed.

Now I defined this:

#ifdef _DEBUG
void dbgprintf(char *szFormat, ...);
#else
#define dbgprintf
#endif

This works fine but under some compilers eg. gcc it will give me a huge
bunch of warnings saying the statement has no effect. This is ofcourse


You can use something like this:

#else
inline void dbgprintf_do_nothing_version_with_ugly_name (char *, ...) { }
#define dbgprintf dgbprintf_do_nothing_version_with_ugly_name
#endif

--
Salu2
Jul 23 '05 #17

This discussion thread is closed

Replies have been disabled for this discussion.