2011-08-31 2 views

답변

10

변수 유형 컴파일러로 알려져 있지만하지에 있습니다 .. func_int 내가 변수 유형은 컴파일 타임에 알려진대로,이에 대한 해결책이있을 수 있습니다 생각

int, 파견 때 전처리 기 (코드를 단순히 구조화되지 않은 텍스트 토큰 스트림으로보고 단순한 대체 조작 만 수행함). 그래서 나는 당신이 C 매크로로 이것을 달성 할 수 없다는 것을 두려워한다.

C++에서는 이러한 문제를 해결하기 위해 템플릿을 발명했습니다.

+0

** C **에서 해결 방법이 있습니까? – lexer

+2

이것은 잘못된 결론입니다. 전처리 기는 * 컴파일러가 분석을 수행 할 수 있도록 매크로 확장을 정렬 할 수있는 경우 인수 유형을 알 필요가 없습니다. gnu 컴파일러에서이 문제를 해결하는 방법은 arnaud576875의 대답을 참조하십시오. 또한 전처리 기는 코드를 구조화되지 않은 텍스트로 보지 않고 중요한 토큰 스트림 *으로 간주합니다. –

1

매크로로는이 작업을 수행 할 수 없습니다. 매크로의 값은 컴파일시에 대체되며 intepreted되지 않습니다. 그것들은 단지 대용품입니다.

11

C1X으로 가능하지만 현재 표준에서는 가능하지 않습니다.

은 다음과 같이 표시됩니다 C89/ANSI C 시간 검사 유형을 실행 할 가능성이 없지만, 그것을 허용하는 지금 gcc 확장이

#define cbrt(X) _Generic((X), long double: cbrtl, \ 
          default: cbrt, \ 
          float: cbrtf)(X) 
+0

이 질문이 Google에서 처음으로 팝업됩니다. 이제 C11을 사용하여 가능합니다. http://en.cppreference.com/w/c/language/generic –

4

. typeof 또는 내가 기억한다면 그 줄을 따라 뭔가. 나는 리눅스 커널에서 그것을 한 번 보았다. kernel.h에서

:

#define min(x, y) ({    \ 
typeof(x) _min1 = (x);   \ 
typeof(y) _min2 = (y);   \ 
(void) (&_min1 == &_min2);  \ 
_min1 < _min2 ? _min1 : _min2; }) 

이 문서를 살펴 보자 내가 처음이 실제로 여기에 질문을보고 GCC hacks in the Linux kernel

을 SO에 대한 :

min macro in kernel.h

나는 당신이 당신의 문제를 해결하는 데 그것을 어떻게 사용하는지 정확히 모르겠지만, 티.

+0

이것은 런타임 유형 검사가 아닙니다. C가 동적으로 입력되지 않았기 때문에 유형을 입력하십시오. 정보는 컴파일시에만 사용 가능하다. – Christoph

1

실제로 변수 유형은 컴파일시 알려지지 만 매크로 확장은 컴파일 전에 수행됩니다. 매크로 대신 2 개의 오버로드 된 함수를 구현하는 것이 좋습니다.

5

유형의 특성을 테스트 할 수 있습니다.

예를 들어 int은 음수 값을 가질 수 있지만 char*은 음수 값을 가질 수 없습니다. 그래서 ((typeof(param))-1) < 0 경우, param은 서명되지 : 컴파일러는 분명히 이것을 최적화

if (((typeof(param))-1) < 0) { 
    do_something_with_int(); 
} else { 
    do_something_with_char_p(); 
} 

.

여기를보십시오 : http://ideone.com/et0v1

이 유형은 다른 크기가 있다면 더 쉽게 될 것이다.

if (__builtin_types_compatible_p(typeof(param), int)) { 
    func_int(param); 
} else if (__builtin_types_compatible_p(typeof(param), char*)) { 
    func_string(param); 
} 

것은 그것을 시도 :

if (sizeof(param) == sizeof(char)) { 
    /* ... */ 
} else if (sizeof(param) == sizeof(char16_t)) { 
    /* ... */ 
} else if (sizeof(param) == sizeof(char32_t)) { 
    /* ... */ 
} else { 
    assert("incompatible type" && 0); 
} 

GCC는 유형의 호환성을 확인 할 수있는 __builtin_types_compatible_p() 내장 기능을 가지고있다 : 다른 문자 크기를 처리 할 수있는 것보다 예를 들어, 당신이 원하는 경우에 일반적인 매크로를 작성하는 여기에 : http://ideone.com/lEmYE

당신이하려고하는 것을 달성하기 위해 매크로에 넣을 수 있습니다 :

#define FUNC(param) ({            \ 
    if (__builtin_types_compatible_p(typeof(param), int)) {   \ 
     func_int(param);            \ 
    } else if (__builtin_types_compatible_p(typeof(param), char*)) { \ 
     func_string(param);           \ 
    }                 \ 
}) 

(({...})GCC's statement expression이며, 일련의 명령문은 rvalue가됩니다.

__builtin_choose_expr() 내장형은 컴파일 할 표현식을 선택할 수 있습니다.

#define FUNC(param)              \ 
    __builtin_choose_expr(__builtin_types_compatible_p(typeof(param), int) \ 
     , func_int(param)             \ 
     , __builtin_choose_expr(__builtin_types_compatible_p(typeof(param), char*) \ 
      , func_string(param)           \ 
      , /* The void expression results in a compile-time error  \ 
       when assigning the result to something. */    \ 
      ((void)0)              \ 
     )                 \ 
    ) 

이 실제로에서 약간 변형 예이다 (이 경우 유효하지 않은 somehting를 컴파일) : PARAM의 유형이 모두 intchar*와 호환성이없는 경우 __builtin_types_compatible_p으로이 컴파일시 오류를 트리거 할 수 있습니다 __builtin_choose_expr docs.

+0

'func_int (x);','func_string (x);'모든 것을'do {} while (0)' –

+0

원래 코드를 닫지 않았다. 'do {} while()'은 매크로가 아니기 때문에 ;-) – arnaud576875

+2

-1'typeof'는 C가 아니라 gcc 확장자입니다. 주소에서 '부호'비트를 설정할 수 없다고 생각하는 이유는 무엇입니까? –