【问题标题】:Predefined Macros for function name __func__函数名 __func__ 的预定义宏
【发布时间】:2013-02-24 15:58:09
【问题描述】:

我正在尝试构建一个调试日志消息函数,用于记录调用日志消息的文件、行和函数。

#define DEBUG_PANIC(p) CLogging::Debuglogf( "Debug marker (%s) - ::%s() in file: %s(%d)", p, __func__ , __FILE__, __LINE__ );

上面的代码适用于一些编译器,但不是全部。我的代码需要与 GCC 以及 Microsoft Visual Studio 交叉兼容。我添加了以下定义以帮助兼容性。

#ifndef __FUNCTION_NAME__
    #if defined __func__ 
        // Undeclared 
        #define __FUNCTION_NAME__   __func__ 
    #elif defined __FUNCTION__ 
        // Undeclared
        #define __FUNCTION_NAME__   __FUNCTION__  
    #elif defined __PRETTY_FUNCTION__
        // Undeclared
        #define __FUNCTION_NAME__   __PRETTY_FUNCTION__
    #else
        // Declared
        #define __FUNCTION_NAME__   "N/A"   
    #endif // __func__ 

#endif // __FUNCTION_NAME__

#define DEBUG_PANIC(p) CLogging::Debuglogf( "Debug marker (%s) - ::%s() in file: %s(%d)", p, __FUNCTION_NAME__, __FILE__, __LINE__ );

上述代码 sn-p 的问题在于 #else 宏在所有编译器上都处于活动状态,而其他宏则不处于活动状态。换句话说,#if defined __func____func__预定义宏 的编译器上为 false。

我的问题是

  • 如何创建交叉编译器宏来查找函数名?
  • 如何判断__func__ 是否可以使用?

【问题讨论】:

标签: c++ visual-studio gcc c-preprocessor


【解决方案1】:

它们既不是预处理器宏,例如__FILE__ and __LINE__, 也不是变量。

取自以下链接:

http://gcc.gnu.org/onlinedocs/gcc-3.2/gcc/Function-Names.html

另外,请查看已回答的与您的问题类似的另一个问题:

How to check if __PRETTY_FUNCTION__ can be used?

例子:

#ifdef _MSC_VER // Visual Studio
    #define FUNCTION_NAME __FUNCTION__
#endif

【讨论】:

    【解决方案2】:

    您假设__func__ 是一个宏,但事实并非如此。这是一个有条件支持的预定义标识符,因此您无法使用#if defined#ifdef 对其进行检查。

    如果编译器无法告诉您这是否受支持(他们可以通过_FUNC_SUPPORTED 或其他方式,我并不是说他们实际上正在这样做),您将不得不检查编译器而不是实际标识符。

    类似的东西:

    #ifndef __FUNCTION_NAME__
        #ifdef WIN32   //WINDOWS
            #define __FUNCTION_NAME__   __FUNCTION__  
        #else          //*NIX
            #define __FUNCTION_NAME__   __func__ 
        #endif
    #endif
    

    【讨论】:

    • 任何符合 C99 或更高版本的 C 编译器必须支持__func__;从这个意义上说,它不是一个可选功能。因此,判断__func__ 受支持的一种方法是检查__STDC_VERSION__ >= 199901L。 (尽管 C99 之前或不符合标准的编译器可以支持它作为扩展。)
    • @KeithThompson 我假设是 C++。但重点是它不是宏。
    • 啊,好点; OP 没有为该语言添加标签。 C++ 标准直到 2011 年才强制要求 __func__。它可能是 C++11 之前编译器的常见扩展。
    【解决方案3】:

    Boost 通常是跨平台解决方案,BOOST_CURRENT_FUNCTION<boost/current_function.hpp> 中定义。

    【讨论】:

      【解决方案4】:

      我想补充一点,__FUNCTION__ 宏是为 GCC 和 MSVC 定义的。虽然是非标准的,但它在两种编译器上都可用。

      GCC Standard Predefined Macros报价:

      C99 引入了__func__,GCC 早就提供了__FUNCTION__。这两个都是包含当前函数名称的字符串(存在细微的语义差异;请参阅 GCC 手册)。它们都不是宏;预处理器不知道当前函数的名称。不过,它们往往与__FILE____LINE__ 结合使用。

      MSVC Predefined Macros报价:

      __FUNCTION__

      仅在函数中有效。将封闭函数的未修饰名称定义为字符串文字。

      如果您使用 /EP 或 /P 编译器选项,则不会扩展__FUNCTION__

      有关示例,请参阅 __FUNCDNAME__

      所以使用__FUNCTION__ 是可以的,因为两个编译器都实现了它。虽然您可能在两种编译器上得到的结果不同,但在某些情况下这可能是可以接受的。

      【讨论】:

      • 我想补充一点,__FUNCTION__ 宏是为 GCC 和 MSVC 定义的。文档引用明确指出这是不是一个宏。
      猜你喜欢
      • 2015-11-29
      • 2021-11-21
      • 2011-01-17
      • 2013-02-14
      • 2020-08-16
      • 2015-08-05
      • 2012-10-21
      • 1970-01-01
      相关资源
      最近更新 更多