0

c89 gcc 4.7.4

I was just experimenting with macros like these:

#define LOG_INFO_1(fmt, ...) printf(fmt, __VA_ARGS__)
#define LOG_INFO_2(...) printf(__VA_ARGS__)

And using like this:

LOG_INFO_1("%s:%d", __func__, __LINE__);
LOG_INFO_2("%s:%d", __func__, __LINE__);

The output gives exactly the same format. I am just wondering what is the advantage of having the fmt argument in my first macro? It doesn't seem to be really needed. How could I make use of it?

1
  • 2
    There is a difference if you only want to pass the format string, e.g. LOG_INFO_1("just a simple string"). When you do that, LOG_INFO_1 will result in a compiler error, due to the trailing comma in the call to printf (since __VA_ARGS__ expands to the empty string in that case), whereas LOG_INFO_2 will expand correctly. Commented Oct 23, 2012 at 17:16

3 Answers 3

5

Specifying that the first parameter is fmt makes no difference to the compiler/computer.

However, I think it makes a big difference to other programmers who may use your code.

Looking at LOG_INFO_1(fmt, ...), I see a strong hint that this macro takes a printf-style format string with additional parameters after.

Looking at LOG_INFO_2(...), I have no idea what parameters should be passed, or in what order. Maybe the first parameter should be a RFC 5424 severity code? Maybe it should be an output stream to write to? Nothing in the macro hints at the answer.

I think you should make work easier for the programmers who come after you by specifying as much as possible, and only leaving ambiguities such as ... only where absolutely necessary.

Sign up to request clarification or add additional context in comments.

Comments

2

For macros it does not matter which variation you use. The preprocessor will produce the same C code from both macros.


For variadic functions at least one argument needs to be defined.

So

void foo(const char * fmt, ...);

would compile, whereas

void bar(...);

wouldn't.

Comments

1

Take a look at ACE_DEBUG/Log_Msg. ACE (adaptive communications environment) is an established c++ framework for networking. They've implemented a thread-safe logging architecture using macros and variadic variables in a similar way.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.