46

In the C language, __FUNCTION__ can be used to get the current function's name. But if I define a function named a() and it is called in b(), like below:

b() { a(); } 

Now, in the source code, there are lots of functions like b() that call a(), e.g. c(), d(), e()...

Is it possible, within a(), to add some code to detect the name of the function that called a()?

Further:

  1. Sorry for the misleading typo. I have corrected it.
  2. I am trying to find out which function calls a() for debugging purposes. I don't know how you do when in the same situation?
  3. And my code is under vxWorks, but I am not sure whether it is related to C99 or something else.
13
  • Not sure. But this maybe helpful to you Commented Apr 19, 2013 at 8:10
  • Why do you want to do this? Is it for debugging purpose? Commented Apr 19, 2013 at 8:13
  • If this is only for debugging you can define a as a macro, that way using __func__ will return b, as you want. Commented Apr 19, 2013 at 8:15
  • Which compiler has FUNCTION to return the name of the current function? The identifier that is foreseen in the C standard for that is __func__ IIRC. Commented Apr 19, 2013 at 8:18
  • what you write is wrong. __FUNC__ returns the current method name AFAIK. To get the caller, you'd have to look at the stacktrace Commented Apr 19, 2013 at 8:19

11 Answers 11

65

There's nothing you can do only in a.

However, with a simple standard macro trick, you can achieve what you want, IIUC showing the name of the caller.

void a() { /* Your code */ } void a_special( char const * caller_name ) { printf( "a was called from %s", caller_name ); a(); } #define a() a_special(__func__) void b() { a(); } 
Sign up to request clarification or add additional context in comments.

5 Comments

I had to declare the caller_name variable as const char* caller_name, but it worked!
Precision: __func__ is part of the C99 standard, [...] __FUNCTION__ is another name for __func__, provided for backward compatibility with old versions of GCC. (source: gcc.gnu.org/onlinedocs/gcc/Function-Names.html)
Could you tell me how can I use your example with ellipsis in function declaration, please? void a(int a, char *fmt, ...) How can I include it in the macro definition?
@mulg0r Have a look at va_list , va_arg and companions. however I doubt you can apply this trick to a function using ellipsis: it should be written with va_list instead, just like the vprintf function series :-(
@mulg0r Using variadic macros you can achieve what you want (eg.#define a(...) a_special (__func__, __VA_ARGS__), for a function void a_special(char const * caller_name, ...){}) They are around in C since C99 and in C++ since C++11.
16

You can do it with a gcc builtin.

void * __builtin_return_address(int level)

The following way should print the immediate caller of a function a().

Example:

a() { printf ("Caller name: %pS\n", __builtin_return_address(0)); } 

2 Comments

This does print return address (still useful), but not function name.
If anyone reading this has the rep for a 1-character edit, there is now an https version of the linked URL.
15

If you are using Linux system, you can use the backtrace() function.

See the man page for more details and a code example.

2 Comments

In late 2020 it's available on macOS too.
If anyone reading this has the rep for a 1-character edit, there is now an https version of the linked URL.
10

Try this:

void a(<all param declarations to a()>); #ifdef DEBUG # define a(<all params to a()>) a_debug(<all params a()>, __FUNCTION__) void a_debug(<all params to a()>, const char * calledby); #endif void b(void) { a(<all values to a()>); } #ifdef DEBUG # undef a #endif void a(<all param declarations to a()>) { printf("'%s' called\n", __FUNCTION__); } #ifdef DEBUG void a_debug(<all param declarations to a()>, const char * calledby) { printf("'%s' calledby '%s'", __FUNCTION__, calledby); a(<all params to a()>); } #endif 

If for example <all param declarations to a()> is int i, double d, void * p then <all params to a()> is i, d, p.


Or (less evil ;->> - but more code modding, as each call to a() needs to be touched):

void a((<all params of normal a()> #ifdef DEBUG , const char * calledby #endif ); void a((<all params of normal a()> #ifdef DEBUG , const char * calledby #endif ) { #ifdef DEBUG printf("'%s' calledby '%s', __FUNCTION__, calledby); #endif ... } ... void b(void) { a(<all params of normal a()> #ifdef DEBUG , __FUNC__ #endif ); } 

__FUNCTION__ is available on GCC (at least?), if using a different C99 compiler replace it with __func__.

1 Comment

:D it looks evil to me to but it IS a cool way of doing it IMO
5

Refer: https://www.gnu.org/software/libc/manual/html_node/Backtraces.html

A backtrace is a list of the function calls that are currently active in a thread. The usual way to inspect a backtrace of a program is to use an external debugger such as gdb. However, sometimes it is useful to obtain a backtrace programmatically from within a program, e.g., for the purposes of logging or diagnostics.

The header file execinfo.h declares three functions that obtain and manipulate backtraces of the current thread.

Comments

2

If you're only after knowing where you were for logging/debug purposes you can use a macro to avoid __func__ giving the name of your logging/debug function but of the function calling it.

Being in a macro will not result in a change to __func__ but will "feel" like using a function.

e.g.

#define LOG(s, data...) log("%s: "s, __function__, ## data) 

3 Comments

Sry, but this does not answer the OP's question.
Since we don't know why they need to do this, it may.
can confirm Joe, it was actually exactly what I was searching for
2

If your platform is Windows, you may use this: walking the callstack

Comments

0

You can tag each function that calls a() with an integer identifier which is passed to a() as a parameter and then use a switch-case construct in a() to tell which function has invoked a().A printf() would tell which function invoked a() depending on the integer identifier value if you use that as an argument to a switch-case construct in a()

#include<stdio.h> void a(int); void b(); void c(); void d(); int main(void) { b(); c(); d(); } void b() { int x=1; a(x); } void c() { int x=2; a(x); } void d() { int x=3; a(x); } void a(int x) { switch(x) { case 1: printf("b called me\n"); break; case 2: printf("c called me\n"); break; case 3: printf("d called me\n"); } } 

4 Comments

It is a "workaround", not a solution. If you need to provide external API - your direct way will be useless.
@DmitrySazonov I answered what the poster asked for.Not more,not less.It IS a solution.
It is not a solution, because you had changed function signature. Nevermind, it just my opinion ;)
Or, you can just pass __FUNCTION__ into a(). No switch required, and it handles new functions, changed function names, etc. Of course, as Dmitry Sazonov says, adding that parameter does change the function's signature.
0

If the function in question is in a different c file, you can do

#define name_of_function(...) \ printf("Function %s is parent\n", __FUNCTION__); \ name_of_function(__VA_ARGS__); 

And at the top of the c file it lives in

#ifdef name_of_function #undef name_of_function #endif 

If they're in the same file, you can wrap the function definition in the second macro, then redefine the first macro at the end. It's not terribly extensible because you can't generate new defines from other defines, but if you're trying to track down parents for a particular function it works without any nonsense.

https://godbolt.org/z/f2jKOm

Comments

0

Use another C-function as a wrapper for the original function which is to debug, means suppress the return data of the original function. Or you need to synchronize return types of the wrapper and the original function.

To avoid type-sync a C-macro should be used as suggested here:

/* You need to debug the function foo(). * So rename foo() to foo_debug() in source and header files. * Then define a macro named foo(). * * Benefits: * - you don't have to care about the return type * of the original function; * - C-macro is inline solution -- there are not * extra calls in the backtrace. */ /* Function which is to debug after renaming. */ type_t foo_debug(); #define foo() \ ({ \ fprintf(stderr, "[DEBUG] %s:%d %s() called by %s\n", \ __FILE__, __LINE__, "foo", __FUNCTION__); \ foo_debug(); \ }) 

Or one line C-macro:

#define foo() (fprintf(stderr, "[DEBUG] %s:%d %s() called by %s\n", __FILE__, __LINE__, "foo", __FUNCTION__), foo_debug()) 

Comments

-1
#include <stdio.h> #include <stdlib.h> 

#define FUNCTION_NAME(FUNCTION) printf("FUNCTION=%s \r\n", #FUNCTION);

int a() { printf("A function call"); } int b() { printf("B function call"); } int main(){ FUNCTION_NAME(a); FUNCTION_NAME(b); return 0; 

}

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.