-3

I want to customize fprintf function for enable/disable Logging

My project use Makefile.

#define ENABLE_LOG 
void log(fmt, ...){
  #ifdef ENABLE_LOG
    va_list vargs;
    va_start(vargs, fmt);
    fprintf(stderr, vargs);
    va_end(vargs);
  #endif
}

log("Test"); # build error
log("TEST %d", 1); # build error

How I can create custom log function that can enable/disable with ENABLE_LOG

Tom Woods
  • 9
  • 4
  • What doesn't work with the above? – Jeffrey May 16 '19 at 17:29
  • 1
    Please create a [mcve] and explain what exactly isn't working. The only thing that stands out to me is that `fmt` needs a type, probably `const char* fmt`. – alter_igel May 16 '19 at 17:30
  • https://stackoverflow.com/questions/20639632/how-to-wrap-printf-into-a-function-or-macro – a1ezh May 16 '19 at 17:31
  • To add to the comment by @alterigel, you also can't have generic statements outside of functions, like the shown calls to `log`. – Some programmer dude May 16 '19 at 17:37
  • Also please take some time to read [the help pages](http://stackoverflow.com/help), take [the SO tour](http://stackoverflow.com/tour), read about [how to ask good questions](http://stackoverflow.com/help/how-to-ask), as well as [this question checklist](https://codeblog.jonskeet.uk/2012/11/24/stack-overflow-question-checklist/). And when asking about build errors, include the actual errors in your question, copy-pasted (as text) in full and complete. – Some programmer dude May 16 '19 at 17:45

1 Answers1

1

You need to use vfprintf(). Also, I would make an empty macro that would avoid a call to an empty function.

#define ENABLE_LOG 
#ifdef ENABLE_LOG
void log(const char *fmt, ...) {
    va_list vargs;
    va_start(vargs, fmt);
    vfprintf(stderr, fmt, vargs);
    va_end(vargs);
}
#else
#define log(fmt, ...)
#endif

Also, note that there is already a C++ function named log. You might consider a different name (especially if you use the dreaded using namespace std; - even though your code looks like pure C.)

001
  • 13,291
  • 5
  • 35
  • 66
  • Empty macro is a dangerous thing. Better make it a void expression: `#define log(fmt, ...) (void)(0)` – Igor G May 16 '19 at 17:51
  • @IgorG I've not heard that. What makes it dangerous? – 001 May 16 '19 at 18:04
  • unpredictable use scenarios do. Some code might get broken (or get interpreted in a different way) if a non-empty sequence of tokens is replaced with an empty token sequence. For example, if some client programmer wanted to log his expressions as they are calculated, he may have `#define LOGGED(expr) (log("Evaluating " #expr), (expr))`. Which would expand to an invalid expression `(, (expr))` if `log()` is empty. This example is rather exotic, I admit. However, to be on the safe side, it's better to have `log()` that always expand to the same type. – Igor G May 16 '19 at 19:35