代码之家  ›  专栏  ›  技术社区  ›  Edd Barrett

在C中获取调用函数的名称(不使用预处理器)

  •  1
  • Edd Barrett  · 技术社区  · 14 年前

    我想知道是否有一种方法可以找到在C中调用当前函数的函数(在运行时)。

    我知道你可以用 __FUNCTION__ 在gcc中,有没有一种不使用c预处理器的方法?

    大概不会。

    干杯

    6 回复  |  直到 14 年前
        1
  •  6
  •   Michael Kohne    14 年前

    不,没有。C不是一种特别内省的语言-像函数名(或调用堆栈的片段)这样的东西在运行时根本不可用。

    如果出于某种原因,您在寻找大量的工作,而没有什么好处,那么您可以使用调试符号构建程序,并且可以编写堆栈遍历和调试符号查找代码。那么你可能会在飞行中发现这一点。但是要小心,因为你在调试信息中看到的符号将被用类型信息装饰,如果你有任何C++的话。

    您已经标记了这个post-gcc,所以相关的细节是可用的,但是这属于“不推荐”和“不保证编译器版本之间是相同的”领域。

        2
  •  6
  •   Vasil Dimov    13 年前

    假设您有一个函数f(),您想从中了解调用者。

    将该函数重命名为f ou func(),并定义一个宏f()来打印 __func__ 然后调用f ou func()。例子:

    void
    f_func()
    {
            do something;
    }
    
    #define f() \
            do { \
                    printf("f called from %s\n", __func__); \
                    f_func(); \
            } while (0)
    
    void
    a()
    {
            f();
    }
    
    void
    b()
    {
            f();
    }
    
    int
    main(int argc, char **argv)
    {
            a();
            b();
    
            return(0);
    }
    
        3
  •  2
  •   Karel Petranek    14 年前

    在运行时中无法获取函数名。唯一的方法是预处理器,但它的功能非常有限。 如果您有可用的调试信息,可以遍历堆栈并从调试信息中获取函数名。然而,这既不是一个健壮的解决方案,也不是一个可移植的解决方案。

        4
  •  1
  •   qrdl    14 年前

    有两个 GNU functions 允许您从backtrace中获取函数地址和名称- backtrace() backtrace_symbols() ,但您需要使用 -rdynamic 旗帜

        5
  •  1
  •   Mogens Raeder    10 年前

    简短的回答是不

    但是有了预处理器,可以这样做

    在C中获取调用函数的名称(使用预处理器)

    假设您有一个函数f(),您只想从中了解调用者以进行调试。

    将该函数重命名为f_func(),并定义一个宏f(),该宏调用一个打印的f版本 芬克 然后在定义调试时调用f_Func()。

    在最终版本中,通过调用真正的函数f_func()来删除信息。

    例子

    #ifdef DEBUG
      #define f(a,b,c) f_debug(a,b,c, __func__)
    #else
      #define f(a,b,c) f_func(a,b,c)
    #endif
    
    bool f_func(int par1, int par2, int par3)
    {
      do_somthing();
    }
    
    bool f_debug((int par1, int par2, int par3, const char calling_func_name[])
    {
      printf("f called from %s\n", calling_func_name); 
      f_func(); 
    }
    
    void a()
    {
      f();
    }
    
    void b()
    {
      f();
    }
    
    int main(int argc, char **argv)
    {
            a();
            b();
    
            return(0);
    }
    

    结果是:

    定义调试时

    从A调用
    从B调用

        6
  •  0
  •   Norman Gray    14 年前

    使用 __func__ 标识符。这个 standard (第6.4.2.2节) 要求 它的存在正是为了这个目的:

    标识符 γ函数 在每个函数定义的左大括号后,翻译器应将声明隐式声明为

    static const char __func__[] = "function-name";
    

    出现在哪里 function-name 是词汇封闭函数的名称。

    正如SteveJessop在评论中指出的那样,这不是预处理器的一部分,而是编译器的固有部分。

    通过遍历堆栈并查看调试符号,很可能有方法找到这个名称。可爱,但很疯狂。