153 votes

Détermination de 32 vs 64 bits en C++

Je suis à la recherche d’un moyen de déterminer de manière fiable si code C++ compilé en 64 bit 32 vs. Nous avons mis au point avec ce que nous pensons est une solution raisonnable à l’aide de macros, mais a été curieux de savoir si les gens pouvaient pensent des cas où cela peut échouer ou s’il y a une meilleure façon de le faire. Veuillez noter que nous essayons de faire cela dans un multi-plateforme, environnement du compilateur multiple.

Merci.

118voto

JaredPar Points 333733

Malheureusement, il n'y a pas de croix-plate-forme de macro qui définit 32 / 64 bits dans les principaux compilateurs. J'ai trouvé le moyen le plus efficace pour ce faire est la suivante.

J'ai d'abord chercher ma propre représentation. Je préfère ENVIRONMENT64 / ENVIRONMENT32. Puis-je savoir ce que tous les principaux compilateurs utilisent pour déterminer si c'est un environnement 64 bits ou pas et l'utiliser pour définir mes variables.

// 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

Une autre voie plus facile est de simplement définir ces variables à partir de la ligne de commande du compilateur.

106voto

Kirill V. Lyadvinsky Points 47627
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;
}

49voto

Contango Points 7976

Malheureusement, il n'existe pas de méthode fiable pour ce faire purement au moment de la compilation.

  • Les deux _WIN32 et _WIN64 peut parfois les deux être indéfini, si les paramètres du projet sont défectueux ou endommagé (notamment sur Visual Studio 2008 SP1).
  • Un projet labellisé "Win32" pourrait être fixé à 64 bits, en raison d'un projet d'erreur de configuration.
  • Sur Visual Studio 2008 SP1, parfois, l'intellisense ne pas gris, les parties appropriées du code, en fonction du courant #define. De ce fait, il est difficile de voir exactement ce qui #define est utilisé au moment de la compilation.

Par conséquent, la seule fiable de la méthode est de combiner 3 vérifications simples:

  • 1) la Compilation de réglage de l'heure, et;
  • 2) le moment de l'Exécution, et;
  • 3) Robuste moment de la compilation, la vérification.

Simple de vérifier 1/3: Compilation de réglage de l'heure

Choisir une méthode pour définir les requis #define variable. Je vous propose la méthode de @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

Simple de vérifier 2/3: moment de l'Exécution

Dans main(), vérifiez pour voir si sizeof() prend tout son sens:

#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

Vérification Simple 3/3: Robuste moment de la compilation, la vérification de

La règle générale est "tous les #define doit se terminer dans un #else qui génère une erreur".

#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

L'Annexe A

Incidentially, les règles ci-dessus peut être adapté pour faire de l'ensemble de votre base de code plus fiable:

  • Chaque instruction if() se termine par un "autre" qui génère un avertissement ou d'erreur.
  • Chaque instruction switch() se termine par un "défaut:" qui génère un avertissement ou d'erreur.

La raison pour laquelle cela fonctionne bien, c'est qu'il vous oblige à penser à tous les cas à l'avance, et ne pas compter sur la (parfois erronées) logique dans le "else" de la partie à exécuter le code correct.

J'ai utilisé cette technique (parmi beaucoup d'autres) d'écrire une ligne de 160 000 projet qui n'a jamais écrasé dans la production au cours des 12 mois de fonctionnement en continu.

44voto

alex tingle Points 3134

Vous devriez être en mesure d'utiliser les macros définies en stdint.h. En particulier, INTPTR_MAX est la valeur que vous avez besoin.

#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

Certains (tous?) les versions de Microsoft compilateur ne viennent pas avec des stdint.h. Je ne sais pas pourquoi, puisque c'est un fichier standard. Voici une version que vous pouvez utiliser: http://msinttypes.googlecode.com/svn/trunk/stdint.h

15voto

mattnewport Points 4809

Qui ne fonctionne pas sur Windows pour commencer. Longs et entiers (ints) est les deux 32 bits si vous êtes la compilation pour windows 32 bits ou 64 bits. Je pense que vérifier si la taille d’un pointeur est 8 octets est probablement une voie plus fiable.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X