2012-09-24 5 views
8

컴파일러에 특정 유형 (예 : ptrdiff_t)이 포함 된 유형으로있는 경우 다시 typedef하지 않으려합니다. 나는 아래 코드가 제대로 작동하지 않는다는 것을 알고 있습니다.특정 유형이 C 컴파일러에 이미 정의되어 있는지 확인하려면 어떻게해야합니까?

#ifndef ptrdiff_t 
    typedef long int ptrdiff_t; 
#endif 
나는 어떤 유형이 이미 C 컴파일러에 정의되어 있는지 확인하려면 어떻게

?

+1

특별한 경우. stddef.h를 포함 시키면 항상 ptrdiff_t를 정의해야합니다. –

+2

특정 정의의 존재 및 특성을 코드에서 테스트 할 수있는 것을 "반영"이라고합니다. 스크립팅 언어는 스크립팅 언어가 비교적 쉽기 때문에 전체 반영을 지원하는 경향이 있습니다. .NET과 JVM도 리플렉션을 지원합니다. 그러나 모국어의 경우 런타임 리플렉션을 지원하려면 많은 추가 실행 코드가 필요합니다. 일부 컴파일 타임 리플렉션은 오버 헤드없이 지원 될 수 있지만 C는 컴파일시에도 사실상 반사 지원을하지 않습니다. – Steve314

+0

cmake 또는 autotools와 같은 도구 사용 – szx

답변

1

당신이 여러 가지 혼란을 조금 있습니다

int, float 같은 종류의 내장 다음은 STND 종류와가 정의 등은, 모든 컴파일러입니다. __int64과 같은 유형은 표준이 아니지만 일부 컴파일러에서 정의됩니다. 그들을 사용하기 위해 아무 것도 할 필요가 없습니다. 동시에 정의되지 않았는지 여부를 코드에서 파악할 수 없습니다. 이것은 컴파일러의 문서에서만 알 수 있습니다. 당신은 쓸 수 있습니다 :

#ifdef MSVC 
     .... Microsoft specific code 
#else 
     .... Code for other compiler. 
#endif 

이 방법을 사용하면 compiler independent environment의 종류를 만들 수 있습니다.

내장 된 유형 외에도 헤더에서 오는 유형이 있습니다. 어떤 헤더들은 다음과 같은 구조를 가지고 있습니다 :

#ifndef ptrdiff_t_DEFINED 
    #define ptrdiff_t_DEFINED 
    typedef long int ptrdiff_t; 
#endif 

매크로 프로세서 defn은 그 유형의 defn과 떨어져 있습니다. 유형이 정의되어 있는지 여부는 확인할 수 없지만 정의가 정의되어 있는지 쉽게 확인할 수 있습니다.

자신이 원하는 코드에 어떤 헤더가 포함되어 있습니까? 이는이 정의가 in the compiler itself이 아님을 의미합니다. 현재 번역 단위의 정의 집합에 있습니다. 컴파일러의 경우에는 자신의 코드로 작성하는 다른 유형 정의와 거의 차이가 없습니다.

위의 예와 같이 "defarding defns"가없는 컴파일러 또는 시스템 헤더가 있습니다. 이 경우에는 수행 할 수있는 유일한 작업은이 헤더를 포함/포함하지 않는 헤더를 추적하고 #include 문장을 사용하여 자신의 #ifdef 경비원을 사용하는 maby입니다.

5

일반적으로 그렇게 할 방법이 없습니다. 어떤 경우에는 사용할 수있는 유형과 동시에 정의 된 매크로가있을 수 있습니다.

특정 예로는 #include <stddef.h>이 있으며, 항상 ptrdiff_t를 정의해야합니다.

0

C 언어 예약 구조를 재정의하면 일반적으로 컴파일 시간 오류가 발생하므로 일반적으로이를 검사 할 수 없습니다. 학업/학습 프로세스에 관심이있는 경우 유형이 예약되어 있는지 여부를 감지하기 위해 C 프로그램의 예외/오류를 확인하기위한 기본 컴파일러 통과를 작성할 수 있습니다. 귀하의 질문에

4

다른 사람들이 말했듯이, 이것에 대한 좋은 일반적인 해결책은 없습니다. 유형 이름은 전처리기에 표시되지 않으므로 #ifdef을 사용하여 유형 이름을 테스트 할 수 없습니다.

그러나 부분적인 솔루션에는 여러 가지가 있으며, 해당 유형에 대한 요구 사항의 출처에 따라 다릅니다.

1990 년, 1999 년 및 2011 년에 발행 된 ISO C 표준의 여러 버전이 있습니다.각각의 새로운 표준 (이론적으로)은 이전의 표준을 대체하고 대체하며, 각각은 새로운 유형을 정의합니다. 예를 들어 1999 C 표준은 <stdbool.h><stdint.h>bool, int32_t 등의 헤더를 추가했습니다. bool 유형을 사용하려고하지만 C99을 지원하지 않는 구현으로 이식 가능한 코드를 원한다면 같은 :

#if defined(__STDC__) && __STDC_VERSION__ >= 199901L 
#include <stdbool.h> 
#else 
typedef enum { false, true } bool; 
#endif 

enum 유형이 같은 정확히을 작동하지 않습니다 C99의 내장 bool 유형, 당신은 당신이 그것을 사용하는 방법에 약간의 조심해야하므로.

유형 uintptr_t<stdint.h>으로 정의됩니다. 그것은 정보의 손실없이 변환 된 void* 포인터 값을 보유 할 수있는 부호없는 유형입니다. 그러한 부호없는 타입을 가지지 않는 구현체 (예를 들어, 포인터가 어떤 정수형보다 크므로)는 그것을 제공하지 않을 것입니다. 직접 유형 자체에 대한 테스트 할 수 없습니다,하지만 당신은 그 경계를주는 매크로 테스트 할 수 있습니다

#include <stdint.h> 

#ifdef UINTMAX_MAX 
/* uintmax_t exists */ 
#else 
/* uintmax_t doesn't exist */ 
#endif 

당신은 C99을지지 않습니다 경우 __STDC____STDC_VERSION__에 대한 시험이 포장해야 할 수도 있습니다 또는 더 나은.

유형 long long은 C99에 추가 된 사전 정의 된 유형 (라이브러리의 일부가 아님)입니다. 다시 말하지만, 당신은 직접 테스트 할 수는 없지만 그 경계를 정의하는 매크로 테스트 할 수 있습니다

#include <limits.h> 

#ifdef LLONG_MAX 
/* long long exists */ 
#else 
/* long long *probably* doesn't exist */ 
#endif 

마지막으로, 당신은 C에서 직접 할 수없는 일이 있습니다,하지만 당신은 같이 할 수있는 프로그램의 빌드 프로세스의 일부. 예를 들어, POSIX는 POSIX 특정 헤더 <unistd.h>pid_t 유형을 정의합니다 (이것은 getpid() 함수에 의해 리턴 된 프로세스 ID 유형입니다). 당신은 조건부 헤더를 포함 할 수 없습니다 -하지만 당신은 헤더가 존재하지 않는 경우 컴파일에 실패하는 작은 프로그램을 작성할 수 있습니다

#include <unistd.h> 
pid_t dummy; 

이 빌드 프로세스의 일환으로,이 파일을 컴파일하려고합니다. 성공할 경우 구성 헤더에

#define HAVE_PID_T 

과 같은 줄을 추가하십시오. 실패하면, 당신은 다음과 같이 쓸 수 있습니다, 소스 코드에서

#undef HAVE_PID_T 

같은 라인을 추가합니다

#include "config.h" 
#ifdef HAVE_PID_T 
#include <unistd.h> 
/* pid_t exists */ 
#else 
/* pid_t doesn't exist */ 
#endif 

GNU Autoconf 테스트 이런 종류의 자동화하는 방법을 제공합니다,하지만 비판 됐어요 지나치게 복잡하고 다루기 힘들다.

이 모든 것은 유형이 존재하는지 여부를 결정한 후에 해당 정보로 유용하게 사용할 수 있다고 가정합니다. bool과 같은 일부 유형의 경우 거의 동일한 대안을 구현할 수 있습니다. 반면에 pid_t의 경우 프로세스를 처리하는 모든 코드를 #ifdef으로 설정하지 않으면 좋은 대체 수단이 될 수 없습니다. 프로그램이 pid_tgetpid()이없는 시스템에서 작동하지 않는다면, 존재한다고 가정하는 코드를 작성하는 것이 가장 좋습니다. 코드를 제공하지 않는 시스템에서 코드를 컴파일하려고하면 컴파일이 즉시 실패하고 이것이 가능한 최선의 방법 일 수 있습니다.

관련 문제