4

I need a logging function or macro in C language, which should works in Linux, that can accept a format string and a list of arguments, and can append the caller's function name to the output string.

Here is an example. Suppose the logging function (macro) is called smart_log. It looks like:

smart_log(const char *fmt, ...)

The first argument fmt is a format string, just like the format string in printf. Following fmt is a list of additional arguments to feed fmt.

Suppose a function called example_function calls smart_log in this way:

void example_function() {
    smart_log("try to output number %d\n", 1);
}

Then the logging string looks like:

[example_function]: try to output number 1

So the key point is that smart_log append the caller's function to the format string.

I am not sure how to achieve this in C. I think it may be possible to use macro to achieve this.

RandyTek
  • 4,374
  • 3
  • 23
  • 32

4 Answers4

8

There is no portable way for a function to know its caller in C. But you’re right, a macro works:

#define smart_log(...) ( printf("[%s]: ", __func__) , printf(__VA_ARGS__) )

__func__ is defined (C99/C11 6.4.2.2 p.1)

as if, immediately following the opening brace of each function definition, the declaration

static const char __func__[] = "function-name";

appeared, where function-name is the name of the lexically-enclosing function.


Thanks to Hagen von Eitzen for improving my original attempt!

Community
  • 1
  • 1
mafso
  • 5,433
  • 2
  • 19
  • 40
2

This is very system/compiler dependent as the exact incantation to get the function name depends very much on the compiler. For Visual C++, you'd use the macro __FUNCTION__ to get the current function name at compile time.

In order to make sure you get the correct function name logged without putting the macro into every invocation of smart_log, you can invoke your logging function via a macro so the macro that gets you the function name is evaluated in the correct context - if you simple add the macro to the function name, you'll always get the name of your logging function...

So instead of calling this:

smart_log("log message");

You call:

SMART_LOG("log message");

Which in turn is defined to:

#define SMART_LOG(message) smart_log(__FUNCTION__, message)

This is under the assumption that your log function takes the function name as the first parameter, so tweak to suit.

Timo Geusch
  • 24,095
  • 5
  • 52
  • 70
  • Good point, it did sound like the OP wanted a solution that would work in C and C++, and I'm not really aware of a portable macro to achieve that unfortunately. – Timo Geusch Aug 25 '14 at 20:33
  • 1
    The recommendation by @PiotrS. in favor of `__func__` also applies to all C99 and C11 compilers for C (since the C tag is currently included). –  Aug 25 '14 at 20:33
  • Thanks, I wasn't sure if `__func__` was available in C99. – Timo Geusch Aug 25 '14 at 20:35
  • The C++ tag has been removed in the meanwhile, but [this answer](http://stackoverflow.com/a/597081/1741125) says, `__func__` has been included in C++11. – mafso Aug 25 '14 at 20:48
  • 1
    @mafso C++11 § 8.4.1 p8, it is indeed defined per the standard. – WhozCraig Aug 25 '14 at 21:10
2

If you don't want to use macros you can use the stack for that. The smart_log function will be just on top of the function that called it.

See How can one grab a stack trace in C?

Community
  • 1
  • 1
Raydel Miranda
  • 13,825
  • 3
  • 38
  • 60
1

Define a macro - SMART_LOG - which passes __FILE__, __FUNCTION__, and __LINE__ to smart_log as arguments. Then whenever you use SMART_LOG, it automatically provides smart_log with the code location of the caller. Note however that __FUNCTION__ is non-standard, but is available in GCC (and Visual C so I'm lead to believe) see: https://stackoverflow.com/a/597081/191492 ).

Community
  • 1
  • 1
James Morris
  • 4,867
  • 3
  • 32
  • 51