2012-11-09 3 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

남자들! 이건 미친 짓이야! –

+1

이중 매크로가 필요한 이유에 대한 통찰력이 있으십니까? –

+0

매크로 자체를 교체해야하기 때문에 매크로를 두 번 처리해야합니다. –

9

당신이 #x 뭔가를 stringize하려고, 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__) 완전히 "123"결과 (예를 들어) #123로 확장됩니다 STRINGIZE_SIMPLE(__LINE__)으로 변합니다. 휴! 나는 원래의 행동을 원할 때마다 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 ++로 시도합니까? mingw 헤더에'__FUNCTION__'이 정의되지 않았다고 생각합니다. 그것이 이유 일 수 있습니다. –

+0

@sandundhammika :'__FUNCTION__'은 비표준이므로 사용이 보장되지 않습니다. 그것은 버그가 아닙니다. C99 표준 (따라서 C++ 11)은'__func__'을 정의하지만 문자열 리터럴이 아니라 변수입니다. 나는 GCC가'__FUNCTION__'을'__func__'으로 확장 시켰다고 믿습니다. 그러면 오류가 발생할 것입니다. 함수 이름을 인수로 허용하도록 함수를 분할해야합니다. 그러면 문자열 리터럴과 '__func__' 변수가 모두 전달 될 수 있습니다. – GManNickG