If you expose a macro that then calls your function, what's the difference between what OP is saying?
#define LOG(...)\
do{\
if(g_logging_enabled){\
printf("%s:%d: ",__FILE__,__LINE__);\
printf(__VA_ARGS__);\
}\
}while(0)
And having the logging code in a function called by a macro: extern void Log(const char*file,int line,const char*fmt,...);
#define LOG(...) (g_logging_enabled?Log(__FILE__,__LINE__,__VA_ARGS__):(void)0))
With the Log function being along these lines: void Log(const char*file,int line,const char*fmt,...){
printf("%s:%d: ",file,line);
va_list v;
va_start(v,fmt);
vprintf(fmt,v);
va_end(v);
}
(This logging code is deliberately simple; in a realistic system, this would be pages of junk dealing with all manner of log categories, log levels, multiple enable flags and their overrides, log target handling, and whatnot. Absolutely the sort of thing that is 0 fun to keep track of in a macro, even before you consider the fact that it's a ton of code to be pasting everywhere you want to log a string.)If you use a function, then the __FILE__ and __LINE__ expand inside that function and point to the location inside the function rather than the callsite of the function.