2011-03-29 3 views
16

C++에서C++에서 "cerr << (A) << endl"과 같이 형식을 지정하지 않고 C로 값을 인쇄하는 방법은 무엇입니까?

#define DEBUG(A) cerr << (A) << endl; 

무엇이든 그것을 보낼 수 있고 그것을 인쇄 할 수 있습니다. 그러나 C에서는 % d, % c 또는 % s 등으로 해당 유형을 지정해야합니다.하지만 모든 유형을 항상 쓰고 싶지는 않습니다. cerr과 같은 fprintf를 사용하고 싶습니다. 어떻게해야합니까?

예 : C

#define DEBUG(A) X // X is what I want to write 
... 
// in function, when I put 
DEBUG(5);   // I just want to print 5 
// or, with same statement, when I say 
DEBUG('a');  // output : a 
+0

'endl'을 사용 하시겠습니까? 그것은 프로그램을 정말로 느리게 할 흐름을 내뿜습니다. –

+1

부수적으로, 함수와 같은 매크로 형식을 작성하는 경우 표준 표현은 전체 표현식을 괄호로 묶는 것입니다. – Lundin

+5

@mattieu : 예, 그는'endl'을 사용하기를 원합니다 : 프로그램을 느리게하는 디버그에서. 그리고 : 프로그램이 그것을 실행하면서, 콘솔의 각 줄을보고 싶습니다. 플러시하지 않는다는 것은 : 방금 인쇄 한 것을 볼 때가 아니라는 것을 알 수 있습니다. 그건 디버깅을 방해합니다. – towi

답변

30

에서, 예를 들어, 좀 더 쉽게 GNU C Language Extensions :

#define DEBUG(x)             \ 
    ({                \ 
    if (__builtin_types_compatible_p (typeof (x), int))   \ 
     fprintf(stderr,"%d\n",x);        \ 
    else if (__builtin_types_compatible_p (typeof (x), char)) \ 
     fprintf(stderr,"%c\n",x);        \ 
    else if (__builtin_types_compatible_p (typeof (x), char[])) \ 
     fprintf(stderr,"%s\n",x);        \ 
    else               \ 
     fprintf(stderr,"unknown type\n");      \ 

    }) 

이 잘됩니다

DEBUG("hello"); //prints hello 
DEBUG(11110); //prints 11110 

그러나 문자에 대한

, 당신은 좌변와 함께 사용한다, 그렇지 않으면 그 형태는 "INT"입니다 :

C에서
char c='A'; 
DEBUG(c); // prints A 
DEBUG('A'); // prints 65 
+2

'endl'과 같은 효과를 내기 위해'fflush (stderr);'를 매크로 끝에 추가하고 싶습니다. –

+2

stderr은 실제로 버퍼링되지 않으므로 fflush는 불필요합니다. 그리고 stdout은 라인 버퍼이므로,이 경우 \ n이 처리합니다. –

+0

마지막으로, 유용한 데이터를 되 찾는 데 적어도 날아갈 기회를주기 위해'& x'에서'sizeof (x)'바이트를'write'하는 것은 어떻습니까? –

14

에서 당신은 당신이 원하는 방법으로 fprintf()을 사용할 수 없습니다. C에 오신 것을 환영합니다.

C++ I/O 스트림 연산자는 타입 안전하며 연산자 오버로딩을 사용하여 마법을 실현합니다. C에서 사용할 수 없기 때문에 안전하지 않은 형식 문자열 접근 방식을 고수해야합니다.

10

원칙적으로 C에는 오버로드 메커니즘이 없습니다.

#define DEBUG_INT(x) fprintf(stderr, "%d\n", (x)) 
#define DEBUG_CHAR(x) fprintf(stderr, "%c\n", (x)) 
8

는 변환 사양을 제거하는 방법은 없지만, 당신은 C99 컴파일러가 있다면, 당신은 __VA_ARGS__를 사용하고 그것을 만들 수 있습니다 :

당신은, 그러나, 같은 매크로의 수를 정의 할 수 있습니다 사용할 수

#include <stdio.h> 

#define DEBUG(fmt, ...) fprintf(stderr, (fmt), __VA_ARGS__) 

int main(void) { 
    int foo = 42; 
    char *t = "foobar"; 
    DEBUG("%s:%d\n", t, foo); 
    return 0; 
} 
+3

또는 더 쉬운 아직 : 프로그램에서 직접 피 묻은 fprintf() 전화 : – Lundin

+0

@ Konstantin : 그'_ 일반 '키워드에 대한 참조합니까? – pmg

+0

죄송 합니다만 C99가 아니며 새로운 표준 초안에서 나온 것입니다. –

0

, 당신은 신뢰성의 종류를 판별 할 수 없습니다 객체. 따라서 일반적인 프로그래밍을 지원하는 몇 가지 메커니즘을 도입해야합니다. 정보를 입력 유지하는 구조로 모든 개체를 둘러싸 :

enum {type_int, type_double, type_string, /* ... */ } type_t; 
struct { 
     type_t type; 
     void *obj; 
} generic_type; 

을 지금, 당신은 ((generic_type)my_object).type을 전환 할 수 있습니다. 이것은 아마도 당신이 찾고있는 것이 아닙니다.



그러나, 매크로 인수가 문자열 리터럴 또는 뭔가 다른 여부를 알 수있는 간단한 트릭이있다. 매크로 인용 문자 '#'를 사용하면 문자열로 매크로 인수를 설정할 수 있습니다 :

#define DEBUG(x) if (#x[0] == '"') printf("%s\n", x); else printf("%d\n", x) 

는 이제 다음을 수행 할 수 아래쪽에

DEBUG("foo bar"); // prints "foo bar" 
DEBUG(23);   // prints "23" 

을, 이것은 당신에게 못하게 예를 들어 구별하다 intfloat이다.또한, 포인터 - 투 - 문자는 문자열로 인식되지 않습니다 : 일부 시스템에

char *foo = "bar"; 
DEBUG(foo);  // prints the value of foo, not the string pointed to by foo 

double salary; 
DEBUG(salary);  // prints (int)salary, not (double)salary 

, sizeof(double) != sizeof(int). 이것은 매크로 인자의 다른 유형을 더 구별하는 데 도움이 될 수 있지만 확실히 이식 가능하지는 않습니다.



일반적으로 완전히 또한 휴대 성을 유지하면서 일반적인 프로그래밍 지원을 향한 심각한 노력없이이 문제를 해결 할 수 없습니다, 말하기.

제 조언 : 형식 지정자를 사용하는 것뿐입니다. 대신 __VA_ARGS__를 사용

0

, 당신은 단지 다음 수행 할 수 있습니다 GCC는 달리

#define DEBUG(x...) fprintf(stderr, x) 

내장 방법,이 방법을 사용하는 믹스 앤 매치 할 수 있습니다 - 당신이 인쇄 할 수 있습니다 "문자열 = "한 번에 한 가지 유형 대신에. 또한 크기와 타입 비 호환성을 이런 방식으로 처리하지 않을 것입니다 - 빌드 타임에 제외 될 수 있다는 것을 제외하고는 fprintf와 본질적으로 같습니다!