13

Let's say I want to have several types of output messages in my code. One of them is DEBUG, which is printed only, when the code is compiled in Debug mode.

Usually I'd have to write something like

#ifdef DEBUG
    std::cout << "Debug message" << std::endl;
#endif

which is pretty cumbersome and annoying to use in many places.

Is it a good practice to define a macro for the code snippet, so you'd use it this way?

MSG_DEBUG("Debug message")

Or is there any other, more elegant way how to deal with it without macros? I'm interested about possible solutions both in C and C++, as I'm using both languages in different projects.

  • It's not clear from the question why you wouldn't just put the conditional code in a function and call that. Is there some other constraint that would prevent that? – Alex Sep 17 '18 at 8:25
  • @gnat The question you've mentioned is so broad, that most people wouldn't connect it with this topic, especially when they'd be looking this specific question on the Internet. – Eenoku Sep 17 '18 at 8:27
  • 3
    Your question is tagged with both c and c++, however, those are pretty different languages. Can you clarify which one you are talking about? Your example would be perfectly fine in C, but might be better implemented with a constexpr if in C++, for instance. – Jörg W Mittag Sep 17 '18 at 8:42
  • 1
    As an aside, diagnostics should go to STDERR. Also, why not make it depend on NDEBUG like assert() does instead? Then you could define it like #define DEBUG_MSG(MSG) assert(std::cerr << MSG), which tests the stream-state too. – Deduplicator Sep 17 '18 at 9:25
19

Sure, if you're OK with using macros in the first place, then defining a parametrized one rather than keep repeating the same conditional code is certainly preferable by any measure of good coding.

Should you use macros at all? In my view you should, since it's accepted practice in C, and any macro-less solution would require at least something being executed even outside of debug mode. The typical C programmer will pick a slightly ugly macro over unnecessary run-time effort any time.

13

There's an element of personal preference here, but in C++ I prefer to do this in the header file:

#ifdef _DEBUG
    void DebugMessage(...);
#else
    inline void DebugMessage(...) {}
#endif

So that the function is inlined away in release builds, but is a proper function in the debug build so you can have proper type checking, sensible error messages, etc. and the ability to add further functionality (logging maybe?) later.

Obviously, you also need to encase the corresponding definition of the function in the .cpp file in an #ifdef _DEBUG block.

  • But the call overhead is still present here, isn't it? – Eenoku Sep 17 '18 at 16:29
  • 7
    If your compiler will generate code to call a known empty function in a release build, the first and biggest thing you need to do to improve efficiency is get a much better compiler. This is really trivial optimization. – David Thornley Sep 17 '18 at 16:44
  • @Eenoku No, as David says, it'll be removed by any compiler you should use. – Jack Aidley Sep 17 '18 at 17:11
  • 3
    There's a key difference here: the macro (depending on how it's written) would not evaluate its argument expressions, while the function always would. Also, it's undefined behavior to pass non-trivial arguments to varargs functions (and usually triggers compiler warnings). – Sebastian Redl Sep 18 '18 at 7:57
  • 1
2

Definitely, just make sure you're not stepping on the code guidelines given by your team. Make sure no other code in the system tries to reach the same functionality via a general if condition.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.