불행히도, 크로스 플랫폼, 크로스 컴파일러 환경에서는 컴파일 타임에이 작업을 수행 할 수있는 신뢰할 수있는 단일 방법이 없습니다.
- 프로젝트 설정에 결함이 있거나 손상된 경우 (특히 Visual Studio 2008 SP1에서) _WIN32 및 _WIN64 모두 정의되지 않을 수 있습니다 .
- "Win32"로 표시된 프로젝트는 프로젝트 구성 오류로 인해 64 비트로 설정 될 수 있습니다.
- Visual Studio 2008 SP1에서 현재 #define에 따라 인텔리전스가 코드의 올바른 부분을 회색으로 표시하지 않는 경우가 있습니다. 이로 인해 컴파일시 어떤 #define이 사용되고 있는지 정확히 알기가 어렵습니다.
따라서 신뢰할 수있는 유일한 방법은 3 가지 간단한 검사 를 결합하는 것입니다 .
- 1) 컴파일 시간 설정 및;
- 2) 런타임 점검 및
- 3) 강력한 컴파일 시간 확인 .
간단한 확인 1/3 : 컴파일 시간 설정
필요한 #define 변수 를 설정 하는 방법을 선택하십시오 . @JaredPar의 방법을 제안합니다.
// Check windows
#if _WIN32 || _WIN64
#if _WIN64
#define ENV64BIT
#else
#define ENV32BIT
#endif
#endif
// Check GCC
#if __GNUC__
#if __x86_64__ || __ppc64__
#define ENV64BIT
#else
#define ENV32BIT
#endif
#endif
단순 점검 2/3 : 런타임 점검
main ()에서 sizeof ()가 의미가 있는지 다시 확인하십시오.
#if defined(ENV64BIT)
if (sizeof(void*) != 8)
{
wprintf(L"ENV64BIT: Error: pointer should be 8 bytes. Exiting.");
exit(0);
}
wprintf(L"Diagnostics: we are running in 64-bit mode.\n");
#elif defined (ENV32BIT)
if (sizeof(void*) != 4)
{
wprintf(L"ENV32BIT: Error: pointer should be 4 bytes. Exiting.");
exit(0);
}
wprintf(L"Diagnostics: we are running in 32-bit mode.\n");
#else
#error "Must define either ENV32BIT or ENV64BIT".
#endif
간단한 검사 3/3 : 강력한 컴파일 시간 검사
일반적인 규칙은 "모든 #define은 오류를 생성하는 #else로 끝나야합니다"입니다.
#if defined(ENV64BIT)
// 64-bit code here.
#elif defined (ENV32BIT)
// 32-bit code here.
#else
// INCREASE ROBUSTNESS. ALWAYS THROW AN ERROR ON THE ELSE.
// - What if I made a typo and checked for ENV6BIT instead of ENV64BIT?
// - What if both ENV64BIT and ENV32BIT are not defined?
// - What if project is corrupted, and _WIN64 and _WIN32 are not defined?
// - What if I didn't include the required header file?
// - What if I checked for _WIN32 first instead of second?
// (in Windows, both are defined in 64-bit, so this will break codebase)
// - What if the code has just been ported to a different OS?
// - What if there is an unknown unknown, not mentioned in this list so far?
// I'm only human, and the mistakes above would break the *entire* codebase.
#error "Must define either ENV32BIT or ENV64BIT"
#endif
2017-01-17 업데이트
의 의견 @AI.G
:
4 년 후 (이전에 가능했는지 알 수 없음) 정적 어설 션을 사용하여 런타임 검사를 컴파일 타임으로 변환 할 수 있습니다. static_assert (sizeof (void *) == 4) ;. 이제 모든 컴파일 시간에 완료되었습니다 :)
부록
기본적으로 위의 규칙은 전체 코드베이스를보다 안정적으로 만들 수 있습니다.
- 모든 if () 문은 경고 또는 오류를 생성하는 "else"로 끝납니다.
- 모든 switch () 문은 경고 또는 오류를 생성하는 "default :"로 끝납니다.
이것이 잘 작동하는 이유는 모든 사례를 미리 생각하고 올바른 코드를 실행하기 위해 "else"부분의 (때로는 결함이있는) 논리에 의존하지 않기 때문입니다.
나는이 기술을 (다른 많은 것들 중에서도) 처음으로 생산 한 날로부터 12 개월 전에 완벽하게 작동 한 30,000 개의 라인 프로젝트를 작성하기 위해 사용했다.