146

C++ コードが 32 ビットと 64 ビットのどちらでコンパイルされているかを確実に判断する方法を探しています。私たちは、マクロを使用して合理的な解決策であると考えるものを思いつきましたが、これが失敗する可能性のあるケースを人々が考えられるかどうか、またはこれを行うためのより良い方法があるかどうかを知りたいと思っていました. クロスプラットフォームの複数のコンパイラ環境でこれを実行しようとしていることにご注意ください。

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

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

ありがとう。

4

16 に答える 16

110

残念ながら、主要なコンパイラ間で 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

もう 1 つの簡単な方法は、コンパイラ コマンド ラインからこれらの変数を設定することです。

于 2009-10-01T18:26:32.537 に答える
105
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;
}
于 2009-10-01T18:32:35.667 に答える
47

残念ながら、クロスプラットフォーム、クロスコンパイラ環境では、これを純粋にコンパイル時に実行するための単一の信頼できる方法はありません。

  • プロジェクト設定に欠陥があるか破損している場合(特に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年1月17日更新

からのコメント@AI.G

4年後(以前は可能かどうかはわかりません)、static assert:static_assert(sizeof(void *)== 4);を使用して、実行時チェックをコンパイル時チェックに変換できます。今ではすべてコンパイル時に行われます:)

付録A

ちなみに、上記のルールは、コードベース全体の信頼性を高めるために適合させることができます。

  • すべてのif()ステートメントは、警告またはエラーを生成する「else」で終了します。
  • すべてのswitch()ステートメントは、警告またはエラーを生成する「default:」で終了します。

これがうまく機能する理由は、正しいコードを実行するために「else」部分の(場合によっては欠陥のある)ロジックに依存せずに、すべてのケースを事前に考える必要があるためです。

私はこの手法を(他の多くの手法の中でも)使用して、最初に本番環境に導入された日(12か月前)から問題なく機能する30,000ラインのプロジェクトを作成しました。

于 2012-09-09T11:02:47.657 に答える
36

で定義されているマクロを使用できるはずです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

于 2009-10-01T19:04:39.480 に答える
15

それは最初からWindowsでは機能しません。コンパイルするウィンドウが 32 ビットか 64 ビットかに関係なく、long と int はどちらも 32 ビットです。ポインターのサイズが 8 バイトであるかどうかを確認することは、おそらくより信頼できるルートだと思います。

于 2009-10-01T18:22:48.660 に答える
10

あなたはこれを行うことができます:

#if __WORDSIZE == 64
char *size = "64bits";
#else
char *size = "32bits";
#endif
于 2012-12-27T07:05:32.907 に答える
7
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
于 2012-01-23T12:34:44.523 に答える
4

「64 ビットでコンパイル」は、C++ では明確に定義されていません。

C++ は、int、long、および などのサイズの下限のみを設定しますvoid *。64 ビット プラットフォーム用にコンパイルされた場合でも、int が 64 ビットであるという保証はありません。このモデルでは、たとえば 23 ビットintsizeof(int *) != sizeof(char *)

64 ビット プラットフォームにはさまざまなプログラミング モデルがあります。

あなたの最善の策は、プラットフォーム固有のテストです。次善の移植可能な決定は、64 ビットでより具体的にする必要があります。

于 2009-10-01T19:48:57.353 に答える
3

プログラムが32-bitまたはでコンパイルされているかどうかを判断しようとする方法は、すでに提案されてい64-bitます。

そして、c++11 の機能を使用して、アーキテクチャが自分の考えているものであることを確認できることを付け加えておきますstatic_assert(「リラックスするため」)。

したがって、マクロを定義する場所で:

#if ...
# define IS32BIT
  static_assert(sizeof(void *) == 4, "Error: The Arch is not what I think it is")
#elif ...
# define IS64BIT
  static_assert(sizeof(void *) == 8, "Error: The Arch is not what I think it is")
#else
# error "Cannot determine the Arch"
#endif
于 2015-06-01T16:25:52.260 に答える
3

あなたのアプローチはそれほど遠くありませんでしたが、longintが同じサイズかどうかを確認しているだけです。理論的には、両方とも 64 ビットである可能性があります。その場合、チェックは両方とも 32 ビットであると想定して失敗します。以下は、相対的なサイズではなく、型自体のサイズを実際にチェックするチェックです。

#if ((UINT_MAX) == 0xffffffffu)
    #define INT_IS32BIT
#else
    #define INT_IS64BIT
#endif
#if ((ULONG_MAX) == 0xfffffffful)
    #define LONG_IS32BIT
#else
    #define LONG_IS64BIT
#endif

原則として、最大値を持つシステム定義マクロがある任意のタイプに対してこれを行うことができます。

標準はlong long、32 ビット システムでも少なくとも 64 ビットである必要があることに注意してください。

于 2013-10-07T17:27:07.287 に答える
1

すべての環境でプロジェクト構成を使用できる場合は、64ビットおよび32ビットのシンボルを簡単に定義できます。したがって、次のようなプロジェクト構成があります。

32ビットデバッグ
32ビットリリース
64ビットデバッグ
64ビットリリース

編集:これらは一般的な構成であり、対象となる構成ではありません。好きなように呼んでください。

それができないのなら、私はJaredのアイデアが好きです。

于 2009-10-01T18:38:12.503 に答える
1

32ビットと64ビットのソースを異なるファイルに配置し、ビルドシステムを使用して適切なソースファイルを選択します。

于 2009-10-22T11:42:19.170 に答える