36

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

b()
{
    a();
}

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

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

更远:

  1. 对不起,误导性的错字。我已经纠正了。
  2. 我试图找出哪个函数调用 a() 以进行调试。不知道你遇到同样的情况怎么办?
  3. 而且我的代码在vxWorks下,但我不确定它是否与C99或其他东西有关。
4

10 回答 10

53

没有什么你只能在a中做的。

但是,通过一个简单的标准宏技巧,您可以实现您想要的,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();
}
于 2013-04-19T08:18:05.387 回答
11

您可以使用内置的 gcc 来完成。

void * __builtin_return_address(int level)

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

例子:

a() {
    printf ("Caller name: %pS\n", __builtin_return_address(0));
}
于 2018-08-07T09:55:39.060 回答
10

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

有关更多详细信息和代码示例,请参见手册页

于 2013-04-19T08:22:11.897 回答
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


或者(不那么邪恶 ;->> - 但更多的代码修改,因为每次调用 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
    );
}

__FUNCTION__在 GCC 上可用(至少?),如果使用不同的 C99 编译器将其替换为__func__.

于 2013-04-19T08:15:52.147 回答
3

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

回溯是线程中当前处于活动状态的函数调用的列表。检查程序回溯的常用方法是使用外部调试器,例如 gdb。然而,有时以编程方式从程序中获取回溯是有用的,例如,出于日志记录或诊断的目的。

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

于 2015-04-21T06:02:05.823 回答
2

如果您只是在知道您在哪里进行日志记录/调试之后,您可以使用宏来避免__func__给出您的日志记录/调试函数的名称,而是给出调用它的函数的名称。

处于宏中不会导致更改,__func__但会“感觉”像使用函数。

例如

#define LOG(s, data...) log("%s: "s, __function__, ## data)
于 2013-04-19T08:20:20.583 回答
2

如果你的平台是 Windows,你可以使用这个:walking the callstack

于 2013-04-19T08:38:29.163 回答
0

您可以使用作为参数传递给a()的整数标识符标记调用a()的每个函数,然后在a()中使用switch-case构造来判断哪个函数调用 了 a() .A printf()如果您将其用作 a() 中 switch-case 构造的参数,将根据整数标识符值 告诉哪个函数调用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");
}

}
于 2013-04-19T08:14:12.347 回答
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

于 2019-10-05T00:35:06.973 回答
-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;

}

于 2017-04-25T20:06:25.410 回答