在C语言中,__FUNCTION__
可用于获取 当前 函数的名称。
但是,如果我定义一个名为a()的函数,并在b()中调用它,如下所示:
b()
{
a();
}
现在,在源代码中,有很多函数,比如b()调用a(),例如c(),d(),e()......
是否可以在()中添加一些代码来检测调用()函数的名称?
此外:
答案 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
);
}
__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来实现。
以下方法应打印函数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
如果它们在同一文件中,则可以将函数定义包装在第二个宏中,然后在最后重新定义第一个宏。 它不是十分可扩展的,因为您不能从其他定义中生成新的定义,但是,如果您试图跟踪某个特定功能的父项,那么它将毫无用处地工作。