Jump to content
  • Advertisement
Sign in to follow this  
fpsgamer

[C/C++] Preprocessor Curiosity:

This topic is 3990 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I am curious why the following works ...
#ifdef DEBUG
#define DEBUG_STRING printf
#elseif
#define DEBUG_STRING
#endif

...

DEBUG_STRING("This is the number %d", 5);


If the DEBUG token is defined the last line expands to: printf("This is the number %d", 5); If the DEBUG token is not defined the last line expands to: ("This is the number %d", 5); Why does the above line still compile in a C/C++ program ? ... it doesn't seem to match any defined syntax. Does the compiler ignore it ? Or does it end up in the binary anyways?

Share this post


Link to post
Share on other sites
Advertisement
Why not?

String is a valid statement - it's not assigned to anything.
5 is a valid statement - it's also not assigned anywhere.
Comma is a valid operation concatenation operator.
Parenthesis are valid to group the above statements.

(5); // valid
("xxx"); // valid
6, 5; // valid
// combination of all above is also valid



A smart compiler will not generate any code for the above, since it doesn't affect any global state. The string might still end up in executable.

This is also a nice example of why macros are evil.

Share this post


Link to post
Share on other sites
Quote:
Original post by Antheus
...This is also a nice example of why macros are evil.


Could you suggest a better way to write that code? I am able to wipe preprocessor directives from every place in my code except in debug statements like those.

Share this post


Link to post
Share on other sites
Your class doesn't derive from itself since the define comes after the class definition.

Your class cannot derive from itself. That would cause a compiler error.

Share this post


Link to post
Share on other sites
Quote:
Original post by fpsgamer
Quote:
Original post by Antheus
...This is also a nice example of why macros are evil.


Could you suggest a better way to write that code? I am able to wipe preprocessor directives from every place in my code except in debug statements like those.


Template based vararg cout.

Share this post


Link to post
Share on other sites
Quote:
Original post by Crypter
I managed to derive a class from itself with a macro trick:

ProgrammersHeaven post

11: Thou Shall Not Do That Again [grin]

The main idea behind writing code in a high level is to be able to modify it later. For that, you have to understand it. There is no way someone is going to understand that without spending some time to devise that you cApplication is in fact not a cApplication, despite the fact that it's still a cApplication. Your code is even more evil than the macro above [smile].



Share this post


Link to post
Share on other sites
Quote:
Original post by Crypter
I managed to derive a class from itself with a macro trick

Your class does not derive from itself. You declare the cWinApplication before the define, and that line will not be rewritten. So, it's still a cWinApplication that derives from cApplication.
The only thing the define does, is make all the method implementations more cryptic (although that suits your nick [wink]). Methods that you declared to be part of cWinApplication, suddenly *SEEM* to be implemented in cApplication.
Apart from that, if you'd decide to put a method using a cApplication* in the abstract base class, the compiler will spew out all kinds of error when you try to implement it, since you suddenly use cWinApplication-pointers.

So, best to skip the define, and just type the three extra letters in the implementation.

Share this post


Link to post
Share on other sites
Quote:
Original post by DaBono
So, best to skip the define, and just type the three extra letters in the implementation.


Or, better yet, solution 1°:

namespace Interfaces { class Application {}; }
class WinApplication : public Interfaces::Application {};
typedef WinApplication Application;


Solution 2°:

template <typename Strategy> class ApplicationAdapter {};
class WinApplicationStrategy {};
typedef ApplicationAdapter<WinApplicationStrategy> Application;


As for the "macro versus template" argument, there is one thing that macros can do that templates cannot: remove code—even if the actual output is suppressed by a certain template, the arguments to the output operators will still be evaluated if they are not trivial (an evaluation cost which can get annoying if you're computing something large for debugging purposes). Ultimately, my approach to debug statements (when I don't use the debugger, which is quite rare these days) is the following:

#ifdef DEBUG
#define DEBUG_OUT(X) do { std::clog << X << std::flush; } while(0)
#else
#define DEBUG_OUT(X) do {} while(0)
#endif

DEBUG_OUT("This is the number" << 5);

Share this post


Link to post
Share on other sites
Quote:
Original post by Emmanuel Deloget
Quote:
Original post by Crypter
I managed to derive a class from itself with a macro trick:

ProgrammersHeaven post

11: Thou Shall Not Do That Again [grin]

The main idea behind writing code in a high level is to be able to modify it later. For that, you have to understand it. There is no way someone is going to understand that without spending some time to devise that you cApplication is in fact not a cApplication, despite the fact that it's still a cApplication. Your code is even more evil than the macro above [smile].


No worries--I have not, and will not![grin]

I was tired that day of coding--we all have been there!

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!