我正在尝试构建一个调试日志消息函数,该函数记录调用日志消息的位置的文件,行和函数。
#define DEBUG_PANIC(p) CLogging::Debuglogf( "Debug marker (%s) - ::%s() in file: %s(%d)", p, __func__ , __FILE__, __LINE__ );
上面的代码适用于某些编译器,但不是全部。我的代码需要与GCC以及Microsoft Visual工作室交叉兼容。我已添加以下定义以帮助兼容性。
#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__ );
上面代码片段的问题在于#else宏在所有编译器上都处于活动状态,而其他宏则没有。换句话说,#if defined __func__
在__func__
是预定义宏的编译器中为false。
我的问题是
__func__
? 答案 0 :(得分:22)
你假设__func__
是一个宏,但事实并非如此。这是有条件支持的预定义标识符,因此您无法使用#if defined
或#ifdef
进行检查。
如果编译器无法告诉你这是否支持(它们可以通过_FUNC_SUPPORTED
或其他东西,我不是说它们实际上是这样做的),你将不得不检查编译器而不是实际的标识符。
有些事情:
#ifndef __FUNCTION_NAME__
#ifdef WIN32 //WINDOWS
#define __FUNCTION_NAME__ __FUNCTION__
#else //*NIX
#define __FUNCTION_NAME__ __func__
#endif
#endif
答案 1 :(得分:10)
通常Boost是在<boost/current_function.hpp>
中定义BOOST_CURRENT_FUNCTION
的跨平台解决方案。
答案 2 :(得分:6)
它们既不是预处理器宏,也不是
__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
答案 3 :(得分:4)
我想补充一点,GCC和MSVC都定义了__FUNCTION__
宏。虽然是非标准的,但它可以在两个编译器上使用。
GCC Standard Predefined Macros引用:
C99介绍
__func__
,GCC长期提供__FUNCTION__
。这两个都是包含当前函数名称的字符串(存在轻微的语义差异;请参阅GCC手册)。它们都不是宏观;预处理器不知道当前函数的名称。不过,它们往往与__FILE__
和__LINE__
结合使用。
__FUNCTION__
仅在函数中有效。将封闭函数的未修饰名称定义为字符串文字。
如果使用/ EP或/ P编译器选项,
__FUNCTION__
不会展开。请参阅
__FUNCDNAME__
以获取示例。
所以使用__FUNCTION__
就行了,因为两个编译器都实现了它。虽然您可能无法在两个编译器上获得相同的结果,但在某些情况下这可能是可以接受的。