我们如何知道调用者函数名称?

时间:2013-04-19 08:07:12

标签: c

在C语言中,__FUNCTION__可用于获取 当前 函数的名称。 但是,如果我定义一个名为a()的函数,并在b()中调用它,如下所示:

b()
{
    a();
}

现在,在源代码中,有很多函数,比如b()调用a(),例如c(),d(),e()......

是否可以在()中添加一些代码来检测调用()函数的名称?

此外:

  1. 对于误导性错字感到抱歉。我纠正了它。
  2. 我试图找出哪个函数调用a()进行调试。一世 不知道你在同样的情况下怎么做?
  3. 我的代码在vxWorks下,但我不确定它是否与C99或 别的什么。

10 个答案:

答案 0 :(得分:39)

只有在。

中才能做到

然而,通过一个简单的标准宏技巧,你可以实现你想要的,IIUC显示调用者的名字。

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();
}

答案 1 :(得分:9)

试试这个:

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

例如,如果<all param declarations to a()>int i, double d, void * p,则<all params to a()>i, d, p


或(更少邪恶; - &gt;&gt; - 但更多代码修改,因为每次调用a()都需要触及):

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
    );
}

如果使用不同的C99编译器将其替换为__FUNCTION__,那么

__func__可用于GCC(至少?)。

答案 2 :(得分:7)

如果您使用的是Linux系统,则可以使用backtrace()功能。

有关详细信息和代码示例,请参阅man page

答案 3 :(得分:2)

如果您的平台是Windows,则可以使用:walking the callstack

答案 4 :(得分:2)

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

  

回溯是当前活动的函数调用的列表   在一个线程中。检查程序回溯的常用方法是   使用外部调试器,如gdb。但是,有时它很有用   从程序内以编程方式获得回溯,例如,   用于记录或诊断。

     

头文件execinfo.h声明了三个获取和的函数   操纵当前线程的回溯。

答案 5 :(得分:2)

您可以使用内置的gcc来实现。

  

void * __builtin_return_address(int level)

以下方法应打印函数a()的直接调用者。

示例:

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

答案 6 :(得分:1)

如果您只知道自己的日志/调试目的,可以使用宏来避免__func__给出日志/调试函数的名称,但是调用它的函数。

在宏中,不会导致对__func__的更改,但会“感觉”像使用某个函数。

e.g。

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

答案 7 :(得分:0)

您可以使用整数标识符标记调用 a()的每个函数,该标识符作为参数传递给 a(),然后使用开关 - 案例 a()中构建,以告知哪个函数已调用 a() .A printf()会告诉调用哪个函数 a(),如果您将其用作 a()

中的switch-case结构的参数,则取决于整数标识符值
#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");
}

}

答案 8 :(得分:0)

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

#define FUNCTION_NAME(功能)printf(“功能 =%s \ r \ n”,#功能);

int a() {
  printf("A function call");
}

int b() {
  printf("B function call");
}

int main(){
FUNCTION_NAME(a);
FUNCTION_NAME(b);
return 0;

}

答案 9 :(得分:0)

如果相关函数位于其他c文件中,则可以

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

它位于c文件的顶部

#ifdef name_of_function
#undef name_of_function
#endif

如果它们在同一文件中,则可以将函数定义包装在第二个宏中,然后在最后重新定义第一个宏。 它不是十分可扩展的,因为您不能从其他定义中生成新的定义,但是,如果您试图跟踪某个特定功能的父项,那么它将毫无用处地工作。

https://godbolt.org/z/f2jKOm