[c++] C ++에서 32 비트와 64 비트 결정

C ++ 코드가 32 대 64 비트로 컴파일되는지 여부를 확실하게 결정하는 방법을 찾고 있습니다. 우리는 매크로를 사용하여 합리적인 솔루션이라고 생각하는 것을 생각해 냈지만 사람들이 이것이 실패 할 수있는 경우를 생각할 수 있는지 또는 더 좋은 방법이 있는지 알고 싶어했습니다. 우리는 크로스 플랫폼, 다중 컴파일러 환경 에서이 작업을 시도하고 있습니다.

#if ((ULONG_MAX) == (UINT_MAX))
# define IS32BIT
#else
# define IS64BIT
#endif

#ifdef IS64BIT
DoMy64BitOperation()
#else
DoMy32BitOperation()
#endif

감사.



답변

불행히도 주요 컴파일러에서 32/64 비트를 정의하는 크로스 플랫폼 매크로는 없습니다. 이 작업을 수행하는 가장 효과적인 방법은 다음과 같습니다.

먼저 내 자신의 표현을 선택합니다. ENVIRONMENT64 / ENVIRONMENT32를 선호합니다. 그런 다음 모든 주요 컴파일러가 64 비트 환경인지 여부를 결정하는 데 사용하는 것을 찾아 내 변수를 설정하는 데 사용합니다.

// Check windows
#if _WIN32 || _WIN64
#if _WIN64
#define ENVIRONMENT64
#else
#define ENVIRONMENT32
#endif
#endif

// Check GCC
#if __GNUC__
#if __x86_64__ || __ppc64__
#define ENVIRONMENT64
#else
#define ENVIRONMENT32
#endif
#endif

또 다른 쉬운 방법은 컴파일러 명령 줄에서 이러한 변수를 설정하는 것입니다.


답변

template<int> void DoMyOperationHelper();

template<> void DoMyOperationHelper<4>()
{
  // do 32-bits operations
}

template<> void DoMyOperationHelper<8>()
{
  // do 64-bits operations
}

// helper function just to hide clumsy syntax
inline void DoMyOperation() { DoMyOperationHelper<sizeof(size_t)>(); }

int main()
{
  // appropriate function will be selected at compile time 
  DoMyOperation();

  return 0;
}


답변

불행히도, 크로스 플랫폼, 크로스 컴파일러 환경에서는 컴파일 타임에이 작업을 수행 할 수있는 신뢰할 수있는 단일 방법이 없습니다.

  • 프로젝트 설정에 결함이 있거나 손상된 경우 (특히 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 개의 라인 프로젝트를 작성하기 위해 사용했다.


답변

에 정의 된 매크로를 사용할 수 있어야합니다 stdint.h. 특히 INTPTR_MAX정확히 필요한 값입니다.

#include <cstdint>
#if INTPTR_MAX == INT32_MAX
    #define THIS_IS_32_BIT_ENVIRONMENT
#elif INTPTR_MAX == INT64_MAX
    #define THIS_IS_64_BIT_ENVIRONMENT
#else
    #error "Environment not 32 or 64-bit."
#endif

Microsoft 컴파일러의 일부 (모두?) 버전은와 함께 제공되지 않습니다 stdint.h. 표준 파일이므로 왜 그런지 확실하지 않습니다. 사용할 수있는 버전은 다음과 같습니다.http://msinttypes.googlecode.com/svn/trunk/stdint.h


답변

Windows에서는 처음에는 작동하지 않습니다. Long과 int는 32 비트 또는 64 비트 창을 컴파일 할 때 32 비트입니다. 포인터의 크기가 8 바이트인지 확인하는 것이 더 안정적인 경로 일 것입니다.


답변

당신은 이것을 할 수 있습니다 :

#if __WORDSIZE == 64
char *size = "64bits";
#else
char *size = "32bits";
#endif


답변

Try this:
#ifdef _WIN64
// 64 bit code
#elif _WIN32
// 32 bit code
#else
   if(sizeof(void*)==4)

       // 32 bit code
   else

       // 64 bit code   
#endif