Je cherche un moyen de déterminer de manière fiable si le code C ++ est compilé en 32 vs 64 bits. Nous avons trouvé ce que nous pensons être une solution raisonnable en utilisant des macros, mais nous étions curieux de savoir si les gens pouvaient penser à des cas où cela pourrait échouer ou s'il existe une meilleure façon de le faire. Veuillez noter que nous essayons de le faire dans un environnement multiplateforme et compilateur multiple.
#if ((ULONG_MAX) == (UINT_MAX))
# define IS32BIT
#else
# define IS64BIT
#endif
#ifdef IS64BIT
DoMy64BitOperation()
#else
DoMy32BitOperation()
#endif
Merci.
c++
32bit-64bit
conditional-compilation
Joe Corkery
la source
la source
stdint.h
peut être votre ami, ou vous devrez peut-être développer vos propres typedefs appropriés.Réponses:
Malheureusement, il n'y a pas de macro multiplateforme qui définit 32/64 bits à travers les principaux compilateurs. J'ai trouvé le moyen le plus efficace de le faire est le suivant.
Je choisis d'abord ma propre représentation. Je préfère ENVIRONMENT64 / ENVIRONMENT32. Ensuite, je découvre ce que tous les principaux compilateurs utilisent pour déterminer s'il s'agit d'un environnement 64 bits ou non et je l'utilise pour définir mes variables.
Une autre méthode plus simple consiste simplement à définir ces variables à partir de la ligne de commande du compilateur.
la source
#if _WIN32 || _WIN64
...#elif __GNUC__
...#else
# error "Missing feature-test macro for 32/64-bit on this compiler."
?la source
size_t
est suffisamment grande pour contenir la taille de tout objet alloué dans le système. C'est généralement ce que vous voulez savoir lors de la compilation conditionnelle. Si ce n'est pas ce que vous voulez, vous pouvez utiliser cet extrait de code avec un autre type au lieu desize_t
. Par exemple, cela pourrait êtrevoid*
.Malheureusement, dans un environnement multiplateforme et compilateur croisé, il n'existe pas de méthode fiable unique pour le faire uniquement au moment de la compilation.
Par conséquent, la seule méthode fiable consiste à combiner 3 vérifications simples :
Contrôle simple 1/3: réglage de l'heure de compilation
Choisissez n'importe quelle méthode pour définir la variable #define requise. Je suggère la méthode de @JaredPar:
Contrôle simple 2/3: contrôle d'exécution
Dans main (), revérifiez pour voir si sizeof () a du sens:
Vérification simple 3/3: Vérification robuste du temps de compilation
La règle générale est "chaque #define doit se terminer par un #else qui génère une erreur".
Mise à jour 2017-01-17
Commentaire de
@AI.G
:Annexe A
Incidemment, les règles ci-dessus peuvent être adaptées pour rendre l'ensemble de votre base de code plus fiable:
La raison pour laquelle cela fonctionne bien est que cela vous oblige à penser à chaque cas à l'avance, et à ne pas vous fier à la logique (parfois imparfaite) de la partie «else» pour exécuter le code correct.
J'ai utilisé cette technique (parmi beaucoup d'autres) pour écrire un projet de 30 000 lignes qui a parfaitement fonctionné depuis le jour où il a été déployé pour la première fois en production (il y a 12 mois).
la source
sizeof(void*)
est-il résolu au moment de la compilation ou de l'exécution? si c'est au moment de la compilation, la vérification sera toujours au moment de l'exécutionif(8!=8){...}
.static_assert(sizeof(void*) == 4);
. Maintenant, tout est fait au moment de la compilation :)static_assert(sizeof(void*) * CHAR_BIT == 32)
est plus expressif et techniquement correct (bien que je ne connaisse aucune architecture où les octets ont une quantité de bits différente de 8)Vous devriez pouvoir utiliser les macros définies dans
stdint.h
. En particulier,INTPTR_MAX
c'est exactement la valeur dont vous avez besoin.Certaines (toutes?) Versions du compilateur de Microsoft ne sont pas fournies avec
stdint.h
. Je ne sais pas pourquoi, car c'est un fichier standard. Voici une version que vous pouvez utiliser:http://msinttypes.googlecode.com/svn/trunk/stdint.hla source
<stdint.h>
et<cstdint>
. En ce qui concerne l'état actuel des choses - la bibliothèque VC ++ provient de Dinkumware (le fait toujours - TR1 a également été pris à partir de là), mais d'après ce que je me souviens avoir lu sur VCBlog, il subit une refactorisation assez importante pour compiler proprement avec/clr
, travailler avec tous les MSVC des types non standard comme__int64
, et ainsi de suite - c'est pourquoi ce n'est pas aussi simple que de le prendre et de le mettre dans la prochaine version du compilateur.Cela ne fonctionnera pas sous Windows pour un début. Les entiers et les entiers sont tous deux 32 bits, que vous compiliez pour des fenêtres 32 bits ou 64 bits. Je pense que vérifier si la taille d'un pointeur est de 8 octets est probablement une route plus fiable.
la source
sizeof(void*) == 8 ? Do64Bit() : Do32Bit();
. Cela pourrait encore laisser une fonction inutilisée dans le binaire, mais l'expression est probablement compilée juste pour un appel à la fonction «droite».template<int> struct Thing; template<> struct Thing<4> { typedef uint32_t type; }; template<> struct Thing<8> { typedef uint64_t type; }; typedef Thing<sizeof(void*)>::type thingtype;
Vous pouvez faire ceci:
la source
la source
«Compilé en 64 bits» n'est pas bien défini en C ++.
C ++ définit uniquement des limites inférieures pour des tailles telles que int, long et
void *
. Il n'y a aucune garantie que int soit 64 bits même lorsqu'il est compilé pour une plate-forme 64 bits. Le modèle permet par exemple 23 bitsint
s etsizeof(int *) != sizeof(char *)
Il existe différents modèles de programmation pour les plates-formes 64 bits.
Votre meilleur pari est un test spécifique à la plateforme. Votre deuxième meilleure décision portable doit être plus spécifique dans ce qui est 64 bits.
la source
Votre approche n'était pas trop éloignée, mais vous ne faites que vérifier si
long
etint
sont de la même taille. Théoriquement, ils pourraient tous les deux être 64 bits, auquel cas votre vérification échouerait, en supposant que les deux soient 32 bits. Voici une vérification qui vérifie en fait la taille des types eux-mêmes, pas leur taille relative:En principe, vous pouvez le faire pour tout type pour lequel vous avez une macro définie par le système avec la valeur maximale.
Notez que la norme exige
long long
au moins 64 bits, même sur les systèmes 32 bits.la source
#include <limits.h>
quelque part avant vos#if
tests.Les gens ont déjà suggéré des méthodes qui tenteront de déterminer si le programme est en cours de compilation dans
32-bit
ou64-bit
.Et je veux ajouter que vous pouvez utiliser la fonctionnalité c ++ 11
static_assert
pour vous assurer que l'architecture est ce que vous pensez qu'elle est ("se détendre").Donc, à l'endroit où vous définissez les macros:
la source
static_assert(sizeof(void*) * CHAR_BIT == 32)
est plus expressif et techniquement correct (bien que je ne connaisse aucune architecture où les octets ont une quantité de bits différente de 8)Le code ci-dessous fonctionne bien pour la plupart des environnements actuels:
la source
_WIN64
nécessite que vous ayez déjà inclus<windows.h>
. Avec Visual C ++, il est préférable d'utiliser le haut-compilateur définit:_M_IX86
,_M_X64
,_M_ARM
,_M_ARM64
, etc.__ppc64__
,__powerpc64__
et_ARCH_PPC64
. Cela attrape également AIX et d'autres plates-formes.Si vous pouvez utiliser des configurations de projet dans tous vos environnements, cela facilitera la définition d'un symbole 64 et 32 bits. Vous auriez donc des configurations de projet comme celle-ci:
Débogage
32 bits Version 32
bits Débogage
64 bits Version 64 bits
EDIT: Ce sont des configurations génériques, pas des configurations ciblées. Appelez-les comme vous voulez.
Si vous ne pouvez pas faire ça, j'aime l'idée de Jared.
la source
Je place les sources 32 bits et 64 bits dans différents fichiers, puis je sélectionne les fichiers source appropriés à l'aide du système de construction.
la source
-DBUILD_64BIT
. Souvent, certaines choses sont très similaires à 32 et 64 bits, donc l'avoir dans le même fichier peut être très pratique.En empruntant à l' excellente réponse de Contango ci - dessus et en la combinant avec " Better Macros, Better Flags " de Fluent C ++, vous pouvez faire:
Ensuite, vous pouvez l'utiliser comme:
Ou en utilisant la macro supplémentaire que j'ai ajoutée:
la source
J'ajoute cette réponse comme cas d'utilisation et exemple complet pour le contrôle d'exécution décrit dans une autre réponse .
C'est l'approche que j'ai adoptée pour indiquer à l'utilisateur final si le programme a été compilé en 64 bits ou 32 bits (ou autre, d'ailleurs):
version.h
test.cc
Compiler et tester
la source