C 我们如何知道调用者函数';她叫什么名字?
在C语言中,C 我们如何知道调用者函数';她叫什么名字?,c,C,在C语言中,\uuuuu函数可用于获取当前函数的名称。 但是如果我定义了一个名为a()的函数,并在b()中调用它,如下所示: b() { a(); } 现在,在源代码中,有很多像b()这样的函数调用a(),例如c(),d(),e() 是否可以在a()中添加一些代码来检测调用a()的函数的名称 进一步: 对不起,有误导性的打字错误。我已经改正了 我试图找出哪个函数调用a()进行调试。我 不知道在同样的情况下你会怎么做 我的代码在vxWorks下,但我不确定它是否与C99相关 还有别的 您
\uuuuu函数
可用于获取当前函数的名称。
但是如果我定义了一个名为a()的函数,并在b()中调用它,如下所示:
b()
{
a();
}
现在,在源代码中,有很多像b()这样的函数调用a(),例如c(),d(),e()
是否可以在a()中添加一些代码来检测调用a()的函数的名称
进一步:
您可以使用传递给a()作为参数的整数标识符标记调用a()的每个函数,然后在a()中使用开关大小写构造来告诉哪个函数调用了a()。aprintf()将根据整型标识符值判断调用了哪个函数a(),如果您将该值用作a()中开关大小写构造的参数
#包括
无效a(int);
无效b();
无效c();
无效d();
内部主(空)
{
b();
c();
d();
}
无效b()
{
int x=1;
a(x);
}
void c()
{
int x=2;
a(x);
}
无效d()
{
int x=3;
a(x);
}
无效a(整数x)
{
开关(x)
{
案例1:
printf(“b称我\n”);
打破
案例2:
printf(“c调用我\n”);
打破
案例3:
printf(“d叫我\n”);
}
}
试试这个:
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
如果使用不同的C99编译器将其替换为
\uuuuuu func\uuuuu
则GCC上提供了\uuuu函数\uuuuuu
(至少?)您只能在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();
}
如果您只是在了解了日志记录/调试的位置之后,才可以使用宏来避免
\uuuu func\uuu
给出您的日志记录/调试函数的名称,而不是调用它的函数的名称
处于宏中不会导致更改为\uuuu func\uuuu
,但会“感觉”像在使用函数
e、 g
如果您使用的是Linux系统,则可以使用
backtrace()
函数
有关更多详细信息和代码示例,请参见 如果您的平台是Windows,您可以使用以下内容:请参阅: 回溯是当前活动的函数调用的列表 在一个线程中。检查程序回溯的常用方法是 使用外部调试器,如gdb。然而,有时它是有用的 以编程方式从程序内获取回溯,例如。, 用于记录或诊断 头文件execinfo.h声明了三个函数,用于获取和 操纵当前线程的回溯
}您可以使用gcc内置组件来完成 下面的方法应该打印函数a()的直接调用方 例如:
a(){
printf(“呼叫者名称:%pS\n”,内置返回地址(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
如果它们在同一个文件中,可以将函数定义包装到第二个宏中,然后在末尾重新定义第一个宏。
它的可扩展性不太好,因为您无法从其他定义生成新的定义,但如果您试图跟踪某个特定函数的父函数,它将毫无意义地工作
不确定。但也许对你有帮助你为什么要这么做?它是为了调试吗?如果这只是为了调试,您可以将a定义为宏,这样使用
\uuuuu func\uuuu
将根据您的需要返回b。哪个编译器具有返回当前函数名称的函数?C标准中预见的标识符是\uu func\uu
IIRC。您编写的是错误的<代码>\uuuu FUNC\uuu返回当前方法名AFAIK。要找到来电者,您必须查看stacktrace:d。我觉得这很糟糕,但这是一种很酷的方式,因为这是一种“解决方法”,而不是解决方案。如果你需要提供外部API-你的直接方式将毫无用处。@DmitrySazonov我回答了海报的要求。不是更多,不是更少。这是一个解决方案。它不是一个解决方案,因为你更改了函数签名。没关系,这只是我的意见;)或者,您可以将\uuuuu函数\uuuu
传递到()。不需要开关,它可以处理新函数、更改的函数名等。当然,正如Dmitry Sazonov所说,添加该参数确实会更改函数的签名。Sry,但这并不能回答OP的问题。因为我们不知道他们为什么需要这样做,它可能会确认Joe,事实上,这正是我要搜索的,我必须将caller\u name变量声明为const char*caller\u name
,但它成功了!精度:\uuuuuu func\uuuu
是C99标准的一部分,[…]\uuuuu FUNCTION\uuuu
是\uuuuu func\uuuu
的另一个名称,用于向后兼容旧版本的GCC。(来源:)你能告诉我如何在函数声明中使用你的带省略号的例子吗void a(int a,char*fmt,…)
如何将其包含在宏定义中?@mulg0r查看va_列表
,va_arg
和相关信息。然而,我怀疑你能用省略号将这个技巧应用到一个函数上:它应该用va_list
来编写,就像vprintf
函数系列一样:-(@mulg0r使用它你可以实现你想要的(例如)(定义一个(…)一个特殊(\u函数,\u va_参数)
,对于一个函数void a_特殊(Cch-const *CalryNoNd,…){} /Cord>)它们在C中是从C99和C++开始的,因为C++ 11.这是打印返回地址(仍然有用),但不是函数名。在2020年底,Mac OS也可用。
#define LOG(s, data...) log("%s: "s, __function__, ## data)
#include <stdio.h>
#include <stdlib.h>
int a() {
printf("A function call");
}
int b() {
printf("B function call");
}
int main(){
FUNCTION_NAME(a);
FUNCTION_NAME(b);
return 0;
#define name_of_function(...) \
printf("Function %s is parent\n", __FUNCTION__); \
name_of_function(__VA_ARGS__);
#ifdef name_of_function
#undef name_of_function
#endif