2012-11-09 26 views
3

我在写一个简单的宏来显示TRACE信息。令牌粘贴和__LINE__

这是我使用的是什么,

#ifdef __DEBUG__ 
#define TRACE { PrintErrorMsg("Trace exception at " __FILE__ "LineNo:"##(__LINE__) "Function: " __FUNCTION__ " ");} 
#else 
#define TRACE 
#endif 

这正与FILE,但它似乎并不与LINE, 任何想法我怎么能对付这个工作。我已经尝试了穿线操作员。其中有 波纹管。

#ifdef __DEBUG__ 
#define TRACE { PrintErrorMsg("Trace exception at " __FILE__ "LineNo:"#(__LINE__) "Function: " __FUNCTION__ " ");} 
#else 
#define TRACE 
#endif 

,并没有PARMS和双PARMS,前 - __LINE__((__LINE__)) 任何想法,我怎么能解决这个问题?

我想出这个,

#ifdef __DEBUG__ 
#define ERROR_MSG_BUF_SIZE 1024 
#define TRACE { char * error_msg_buffer = new char[ERROR_MSG_BUF_SIZE]; \ 
       sprintf(error_msg_buffer,"Trace Exception at file: %s ,Line : %d , Function %s \n",__FILE__,__LINE__,__FUNCTION__);\ 
PrintErrorMsg(error_msg_buffer);\ 
delete[] error_msg_buffer;} 
#else 
#define TRACE 

但我想这样做,而无需使用sprintf的,仅仅只能通过串并标记粘贴。 有什么想法?

#endif 

--Thanks在advance--

+0

为什么你在'__LINE__'周围有括号? –

+0

,因为它不仅属于'_',而且全部属于'__LINE__'。 因为我提到这个:http://stackoverflow.com/questions/9454973/token-pasting-does-not-seem-to-be-working-with-c-macros –

+0

恩,'__LINE__'是令牌。你想'#__ LINE__'。 –

回答

5

你需要这种愚蠢的,很遗憾。

#include <stdio.h> 

#define TRACE2(f,l) printf("I am at file: " f " and line: " #l "\n") 
#define TRACE1(f,l) TRACE2(f,l) 
#define TRACE() TRACE1(__FILE__, __LINE__) 

int main(void) 
{ 
    TRACE(); 
    TRACE(); 
} 

我在文件:TEST.CPP和行:9
我在文件:TEST.CPP和线路:10

+0

WHOP man!这太疯狂了! –

+1

对于为什么需要双宏的任何见解? –

+0

因为你需要将宏本身替换掉,所以你需要将它处理两次。 –

9

当您尝试stringize一些与#x,这x必须是宏参数:

#define FOO #__LINE__ /* this is not okay */ 
#define BAR(x) #x  /* this is okay */ 

但你不能简单地说BAR(__LINE__),因为这种无线将令牌__LINE__转换为BAR,在那里它立即变成没有扩展的字符串(这是设计),给"__LINE__"。令牌粘贴操作符##发生同样的事情:它们的操作数的扩展从不发生。

解决方法是添加间接。你应该总是有这些在你的代码库的地方:

#define STRINGIZE(x) STRINGIZE_SIMPLE(x) 
#define STRINGIZE_SIMPLE(x) #x 

#define CONCAT(first, second) CONCAT_SIMPLE(first, second) 
#define CONCAT_SIMPLE(first, second) first ## second 

现在STRINGIZE(__LINE__)变成STRINGIZE_SIMPLE(__LINE__)其被完全展开,以(例如)#123,这会导致“123”。唷!我要离开STRINGIZE_SIMPLE,我想要原始行为。所以你的代码会是这样的:

#include <iostream> 

#define STRINGIZE(x) STRINGIZE_SIMPLE(x) 
#define STRINGIZE_SIMPLE(x) #x 

#define TRACE()             \ 
     PrintErrorMsg("Trace exception in " __FILE__   \ 
         " at line number " STRINGIZE(__LINE__) \ 
         " in function " __FUNCTION__ ".") 

void PrintErrorMsg(const char* str) 
{ 
    std::cout << str << std::endl; 
} 

int main() 
{ 
    TRACE(); 
} 
+0

感谢您的回答 –

+0

此代码和'__FUNCTION__'在Mingw64版本上失败。 我认为这是一个错误,它适用于Visual C++。 有经验的人请举报。 你用g ++试试这段代码吗? 我觉得'__FUNCTION__'没有在mingw头文件中定义。这可能是原因。 –

+0

@sandundhammika:'__FUNCTION__'是非标准的,所以它的使用是不能保证的。这不是一个错误。 C99标准(因此C++ 11)定义了'__func__',但是作为一个变量,而不是字符串文字。我相信GCC将'__FUNCTION__'展开为'__func__',这会导致错误。你应该分开你的函数以接受函数名称作为参数,然后可以将字符串文字和'__func__'变量传递给它。 – GManNickG