Bestimmen von 32 vs 64 Bit in C ++

136

Ich suche nach einer Möglichkeit, zuverlässig festzustellen, ob C ++ - Code in 32 vs 64 Bit kompiliert wird. Wir haben uns eine unserer Meinung nach vernünftige Lösung mit Makros ausgedacht, waren aber neugierig zu wissen, ob die Leute an Fälle denken könnten, in denen dies fehlschlagen könnte, oder ob es einen besseren Weg gibt, dies zu tun. Bitte beachten Sie, dass wir dies in einer plattformübergreifenden Umgebung mit mehreren Compilern versuchen.

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

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

Vielen Dank.

Joe Corkery
quelle
8
Wenn Sie sich wirklich für die Wortgröße Ihrer Architektur interessieren, übersehen Sie nicht die Möglichkeit, dass es sich weder um 32- noch um 64-Bit handelt. Es gibt 16- und 128-Bit-Architekturen.
Alex Kribbeln
Was ist der Unterschied zwischen der 64-Bit- und der 32-Bit-Operation?
Peterchen
2
Sie sollten dies wirklich nicht von der Wortbreite der Zielplattform abhängig machen. Verwenden Sie stattdessen die Größe der relevanten Datentypen direkt, um zu bestimmen, was zu tun ist. stdint.hMöglicherweise ist es Ihr Freund, oder Sie müssen möglicherweise eigene geeignete Typedefs entwickeln.
Phil Miller
Dieser Test scheint unter Visual Studio 2008 SP1 nicht zu funktionieren. Es bleibt sowohl für 32-Bit als auch für 64-Bit auf "IS64BIT" hängen.
Contango

Antworten:

99

Leider gibt es kein plattformübergreifendes Makro, das 32/64 Bit für die wichtigsten Compiler definiert. Ich habe den effektivsten Weg gefunden, dies zu tun, ist der folgende.

Zuerst wähle ich meine eigene Darstellung. Ich bevorzuge ENVIRONMENT64 / ENVIRONMENT32. Dann finde ich heraus, was alle großen Compiler verwenden, um festzustellen, ob es sich um eine 64-Bit-Umgebung handelt oder nicht, und verwende dies, um meine Variablen festzulegen.

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

Eine andere einfachere Möglichkeit besteht darin, diese Variablen einfach über die Compiler-Befehlszeile festzulegen.

JaredPar
quelle
3
Nun, es gibt neben GCC und VS noch andere Compiler. Zum Beispiel kommen QNX und GHS in den Sinn (obwohl ich vermute, dass QNX ähnliche Build-Time-Definitionen wie GCC hat). Außerdem haben Sie MIPS64- und IA64-Architekturen in Ihrem GCC-Check vergessen
Rom
14
@ Rom, definitiv mehr als 2 Compiler und Architekturen. Dies ist nur ein Beispiel für die Lösung dieses Problems und keine vollständige Lösung.
JaredPar
2
Ich sage "normalerweise". "Ideal" ist wahrscheinlich realistischer.
Steve Jessop
7
Ich denke, Sie sollten "#if defined ( WIN32 ) || defined (_WIN64)" usw. verwenden
KindDragon
3
#if _WIN32 || _WIN64... #elif __GNUC__... #else # error "Missing feature-test macro for 32/64-bit on this compiler."?
Davislor
100
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;
}
Kirill V. Lyadvinsky
quelle
2
Was passiert, wenn size_t weder 4 noch 8 ist?
Jesper
16
@Jesper, dann wird im obigen Beispiel ein Linkfehler angezeigt. Oder Sie könnten DoMyOperation für diesen Fall implementieren
Kirill V. Lyadvinsky
1
Schicke Verwendung von Vorlagen und Lob zum Testen, worauf es ankommt (die Größe eines bestimmten Typs), anstatt zu korrelieren.
Phil Miller
2
Seien Sie vorsichtig mit size_t. Sie können Probleme haben, bei denen es beispielsweise nicht der Zeigergröße entspricht (z. B. auf Plattformen mit mehr als einer Zeigergröße).
Logan Capaldo
8
Standard sagt, dass die Größe von size_tgroß genug ist, um die Größe eines zugewiesenen Objekts im System aufzunehmen. Normalerweise ist es das, was Sie beim bedingten Kompilieren wissen möchten. Wenn es nicht das ist, was Sie wollen, können Sie dieses Snippet mit einem anderen Typ anstelle von verwenden size_t. Zum Beispiel könnte es sein void*.
Kirill V. Lyadvinsky
44

Leider gibt es in einer plattformübergreifenden, compilerübergreifenden Umgebung keine einzige zuverlässige Methode, um dies nur zur Kompilierungszeit zu tun.

  • Sowohl _WIN32 als auch _WIN64 können manchmal beide undefiniert sein, wenn die Projekteinstellungen fehlerhaft oder beschädigt sind (insbesondere in Visual Studio 2008 SP1).
  • Ein Projekt mit der Bezeichnung "Win32" kann aufgrund eines Projektkonfigurationsfehlers auf 64-Bit festgelegt werden.
  • In Visual Studio 2008 SP1 grauisiert der Intellisense manchmal nicht die richtigen Teile des Codes gemäß der aktuellen #define. Dies macht es schwierig, genau zu erkennen, welche #define zur Kompilierungszeit verwendet wird.

Daher besteht die einzig zuverlässige Methode darin, drei einfache Überprüfungen zu kombinieren :

  • 1) Kompilierzeiteinstellung und;
  • 2) Laufzeitprüfung und;
  • 3) Robuste Überprüfung der Kompilierungszeit .

Einfache Prüfung 1/3: Einstellung der Kompilierungszeit

Wählen Sie eine beliebige Methode, um die erforderliche Variable #define festzulegen. Ich schlage die Methode von @JaredPar vor:

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

Einfache Prüfung 2/3: Laufzeitprüfung

Überprüfen Sie in main () noch einmal, ob sizeof () sinnvoll ist:

#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

Einfache Prüfung 3/3: Robuste Prüfung der Kompilierungszeit

Die allgemeine Regel lautet: "Jede #define muss mit einer #else enden, die einen Fehler erzeugt."

#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

Update 2017-01-17

Kommentar von @AI.G:

4 Jahre später (ich weiß nicht, ob es vorher möglich war) können Sie die Laufzeitprüfung mit static assert: static_assert (sizeof (void *) == 4); in die Kompilierungszeit konvertieren. Jetzt ist alles zur Kompilierungszeit erledigt :)

Anhang A

Im Übrigen können die oben genannten Regeln angepasst werden, um Ihre gesamte Codebasis zuverlässiger zu machen:

  • Jede if () - Anweisung endet mit einem "else", das eine Warnung oder einen Fehler generiert.
  • Jede switch () - Anweisung endet mit einem "default:", der eine Warnung oder einen Fehler generiert.

Der Grund, warum dies gut funktioniert, besteht darin, dass Sie gezwungen sind, jeden einzelnen Fall im Voraus zu überlegen und sich nicht auf die (manchmal fehlerhafte) Logik im "else" -Teil zu verlassen, um den richtigen Code auszuführen.

Ich habe diese Technik (unter anderem) verwendet, um ein 30.000-Zeilen-Projekt zu schreiben, das vom ersten Tag an (vor 12 Monaten) einwandfrei funktionierte.

Contango
quelle
sizeof(void*)Wird es zur Kompilierungs- oder Laufzeit aufgelöst? Wenn es zur Kompilierungszeit ist, wird zur Laufzeit immer geprüft if(8!=8){...}.
Ameen
@ameen Es ist zur Laufzeit behoben. Ziel dieser Überprüfung ist es sicherzustellen, dass das Programm mit einem entsprechenden Fehler beendet wird, wenn die Bitigkeit nicht den Erwartungen entspricht. Dies bedeutet, dass der Entwickler diesen Fehler sofort beheben kann, anstatt zu versuchen, subtile Fehler zu diagnostizieren, die später auftreten.
Contango
3
4 Jahre später (ich weiß nicht, ob es vorher möglich war) können Sie die Laufzeitprüfung mit statischer Zusicherung in eine zur Kompilierungszeit konvertieren : static_assert(sizeof(void*) == 4);. Jetzt ist alles zur Kompilierungszeit erledigt :)
Al.G.
1
static_assert(sizeof(void*) * CHAR_BIT == 32)ist ausdrucksvoller und technisch korrekter (obwohl ich keine Architektur kenne, in der Bytes eine andere Anzahl von Bits als 8 haben)
Xeverous
1
Siehe auch meine Antwort unten , die diese hervorragende Antwort mit " Bessere Makros, bessere Flags " von Fluent C ++ kombiniert .
Metall
30

Sie sollten in der Lage sein, die in definierten Makros zu verwenden stdint.h. Insbesondere INTPTR_MAXist genau der Wert, den Sie benötigen.

#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

Einige (alle?) Versionen des Microsoft-Compilers werden nicht mitgeliefert stdint.h. Ich weiß nicht warum, da es sich um eine Standarddatei handelt. Hier ist eine Version, die Sie verwenden können:http://msinttypes.googlecode.com/svn/trunk/stdint.h

Alex Kribbeln
quelle
4
Warum keine stdint.h für Microsoft? Weil es mit dem C99-Standard eingeführt wurde und Microsoft eine aktive Abneigung gegen die Implementierung selbst der einfachsten Dinge von C99 zu haben scheint. Sogar das einfache Bibliotheksmaterial, das keinen Compilerwechsel erfordert. Sogar die Dinge, die bereits beim Kompilieren für C ++ erledigt werden (wie Deklarationen nach Anweisungen). Ich weiß, dass es getestet werden muss usw., aber ich weiß auch, dass MS einen angemessenen Teil seiner Bibliothek von Dinkumware / Plauger bekommt (oder einmal bekommen hat), und Dinkumware hat die C99-Bibliothek schon seit Jahren im Angebot.
Michael Burr
2
VC ++ 2010 (Beta 1 jedenfalls) hat <stdint.h>und <cstdint>. Was den gegenwärtigen Stand der Dinge betrifft - die VC ++ - Bibliothek stammt von Dinkumware (tut es immer noch - TR1 wurde ebenfalls von dort übernommen), aber nach dem, was ich in VCBlog gelesen habe, wird es einer ziemlich bedeutenden Umgestaltung unterzogen, um sauber /clrmit allen MSVC zu kompilieren und zu arbeiten Nicht-Standard-Typen wie __int64und so weiter - weshalb es nicht so einfach ist, es einfach zu nehmen und in die nächste Compiler-Version zu setzen.
Pavel Minaev
2
Dies führte mich zur richtigen Antwort, aber ich denke, Sie sollten mit UINT64_MAX vergleichen, nicht mit INT64_MAX. Ich habe SIZE_MAX == UINT64_MAX verwendet - wahrscheinlich das gleiche
Arno Duvenhage
15

Das funktioniert unter Windows zunächst einmal nicht. Longs und Ints sind beide 32-Bit, unabhängig davon, ob Sie für 32-Bit- oder 64-Bit-Fenster kompilieren. Ich würde denken, dass die Überprüfung, ob die Größe eines Zeigers 8 Bytes beträgt, wahrscheinlich eine zuverlässigere Route ist.

mattnewport
quelle
2
Leider ist sizeof in der # if-Direktive verboten (wenn Sie darüber nachdenken, hat der Präprozessor keine Möglichkeit zu sagen)
EFraim
Ja, deshalb habe ich es so belassen, dass ich vorgeschlagen habe, die Größe eines Zeigers zu überprüfen, anstatt sizeof zu verwenden - ich kann mir keine tragbare Methode
vorstellen
3
Frag nicht (noch) nicht sagen , es hat bei Pre-Prozessor - Zeit zu tun. Viele / die meisten Compiler mit aktivierter Optimierung werden gute Arbeit leisten, um toten Code zu eliminieren, selbst wenn Sie ihn mit einem Test wie "bis zur Laufzeit belassen" sizeof(void*) == 8 ? Do64Bit() : Do32Bit();. Das könnte immer noch eine unbenutzte Funktion in der Binärdatei belassen, aber der Ausdruck wird wahrscheinlich nur zu einem Aufruf der "richtigen" Funktion kompiliert.
Steve Jessop
1
@onebyone, das das Problem von Funktionsaufrufen löst, aber was ist, wenn ich eine Variable basierend auf der Plattform als einen anderen Typ deklarieren möchte, der auf dem Präprozessor ausgeführt werden muss, es sei denn, Sie möchten mehrere Variablen deklarieren und sie basierend auf einer if-Anweisung verwenden ( was auch optimiert werden würde, wenn sie nicht verwendet werden, aber im Code nicht sehr angenehm wären)
Falaina
1
Dann hast du recht, ein konstanter Ausdruck in einer Bedingung ist nicht gut. Kirills Ansatz kann jedoch tun, was Sie wollen: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;
Steve Jessop
9

Sie könnten dies tun:

#if __WORDSIZE == 64
char *size = "64bits";
#else
char *size = "32bits";
#endif
Anoop
quelle
1
In vielen Programmierumgebungen für C- und C-abgeleitete Sprachen auf 64-Bit-Computern sind "int" -Variablen immer noch 32 Bit breit, aber lange Ganzzahlen und Zeiger sind 64 Bit breit. Diese haben ein LP64-Datenmodell. unix.org/version2/whatsnew/lp64_wp.html
Hermes
6
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
emj8321
quelle
7
Dieser Code ist nicht korrekt. Auf 64-Bit sind sowohl _WIN32 als auch _WIN64 definiert. Wenn Sie es umdrehen (zuerst nach _WIN64 suchen), funktioniert es natürlich.
BertR
4

"In 64 Bit kompiliert" ist in C ++ nicht gut definiert.

C ++ legt nur Untergrenzen für Größen wie int, long und fest void *. Es gibt keine Garantie dafür, dass int 64-Bit ist, selbst wenn es für eine 64-Bit-Plattform kompiliert wurde. Das Modell erlaubt zB 23 Bit ints undsizeof(int *) != sizeof(char *)

Es gibt verschiedene Programmiermodelle für 64-Bit-Plattformen.

Ihre beste Wahl ist ein plattformspezifischer Test. Ihre zweitbeste, müssen tragbare Entscheidung spezifischere in sein , was 64 Bit.

Peterchen
quelle
3

Ihr Ansatz war nicht zu weit entfernt, aber Sie prüfen nur, ob longund intsind Sie gleich groß. Theoretisch könnten beide 64 Bit sein. In diesem Fall würde Ihre Prüfung fehlschlagen, vorausgesetzt, beide sind 32 Bit. Hier ist eine Überprüfung, die tatsächlich die Größe der Typen selbst überprüft, nicht ihre relative Größe:

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

Grundsätzlich können Sie dies für jeden Typ tun, für den Sie ein systemdefiniertes Makro mit dem Maximalwert haben.

Beachten Sie, dass der Standard long longauch auf 32-Bit-Systemen mindestens 64 Bit betragen muss.

cmaster - Monica wieder einsetzen
quelle
Eine Sache, die zu beachten ist, damit UINT_MAX und ULONG_MAX definiert werden, möchten Sie wahrscheinlich #include <limits.h>irgendwo vor Ihren #ifTests haben.
Alexis Wilke
3

Die Leute haben bereits Methoden vorgeschlagen, die versuchen festzustellen, ob das Programm in 32-bitoder kompiliert wird 64-bit.

Und ich möchte hinzufügen, dass Sie die c ++ 11-Funktion verwenden können static_assert, um sicherzustellen, dass die Architektur so ist, wie Sie denken ("zum Entspannen").

Also an der Stelle, an der Sie die Makros definieren:

#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
Ameen
quelle
static_assert(sizeof(void*) * CHAR_BIT == 32)ist ausdrucksvoller und technisch korrekter (obwohl ich keine Architektur kenne, in der Bytes eine andere Anzahl von Bits als 8 haben)
Xeverous
2

Der folgende Code funktioniert in den meisten aktuellen Umgebungen einwandfrei:

  #if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) &&     !defined(__ILP32__) ) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__)
    #define IS64BIT 1
 #else
    #define IS32BIT 1
#endif
Alex Byrth
quelle
3
Beachten Sie, _WIN64dass Sie bereits aufgenommen haben <windows.h>. Mit Visual C ++, dann ist es besser , den eingebauten Compiler definiert zu verwenden: _M_IX86, _M_X64, _M_ARM, _M_ARM64etc.
Chuck Walbourn
Für PowerPC, ich glaube , Sie überprüfen müssen __ppc64__, __powerpc64__und _ARCH_PPC64. Das fängt auch AIX und andere Plattformen ein.
jww
1

Wenn Sie Projektkonfigurationen in all Ihren Umgebungen verwenden können, würde dies die Definition eines 64- und 32-Bit-Symbols vereinfachen. Sie hätten also folgende Projektkonfigurationen:

32-Bit-Debug
32-Bit-Release
64-Bit-Debug
64-Bit-Release

BEARBEITEN: Dies sind generische Konfigurationen, keine gezielten Konfigurationen. Rufen Sie sie an, wie Sie wollen.

Wenn du das nicht kannst, mag ich Jareds Idee.

Jon Seigel
quelle
Oder kombinieren Sie beides: Erkennen Sie die Konfiguration auf den Compilern, die Sie kennen, automatisch, aber schauen Sie auf ein #define zurück, das in dem Projekt / der Befehlszeile / was auch immer auf nicht erkannten Compilern angegeben ist.
Steve Jessop
4
Wie wird Ihre VisualStudio-spezifische Lösung bei der plattformübergreifenden Frage des OP helfen?
Alex Kribbeln
3
@ Jon: Hmm. Sie werden per Definition NICHT in plattformübergreifenden Umgebungen unterstützt . Es sei denn, es ist MSs Definition von plattformübergreifend - funktioniert mit neueren Windows-Varianten.
EFraim
1
@EFraim: Ja, Sie können 32- oder 64-Bit mit VS ZIELEN, aber das ist nicht das, worüber ich spreche. Generische Projektkonfigurationen und die Namen, die ich ihnen zuweise, haben absolut nichts mit Plattform zu tun. Wenn Projektkonfigurationen VS-spezifisch sind, ist das eine Schande, weil sie sehr praktisch sind.
Jon Seigel
1
Ich denke das ist die richtige Antwort. Es ist zuverlässiger als der Versuch, Dinge automatisch zu erkennen. Alle IDEs, die ich jemals gesehen habe, unterstützen diese Funktion in irgendeiner Form, und ich wette, diejenigen, die ich noch nie gesehen habe, unterstützen sie auch. Wenn Sie make oder jam verwenden, können Sie die Variablen beim Aufrufen auf die übliche Weise über die Befehlszeile festlegen.
1

Ich würde 32-Bit- und 64-Bit-Quellen in verschiedenen Dateien platzieren und dann mithilfe des Build-Systems geeignete Quelldateien auswählen.

big-z
quelle
2
Dies ähnelt dem Build-System, das Ihnen ein Flag wie z -DBUILD_64BIT. Oft sind bestimmte Dinge sowohl 32- als auch 64-Bit sehr ähnlich, so dass es sehr praktisch sein kann, sie in derselben Datei zu haben.
Alexis Wilke
Das Verwalten von Doppelquelldateien ist fehleranfällig. IMO sogar ein riesiges #if bit64 .. alles Code, für 64bit #else .. alles Code, für 32bit #endif ist besser als das. (# if's Zeile für Zeile ist aus meiner Sicht ideal)
Brewmanz
1

Angelehnt an Contango ‚s ausgezeichnete Antwort oben und es mit‚kombiniert Besseren Makros, Better Flags ‘von Fluent C ++, können Sie tun:

// Macro for checking bitness (safer macros borrowed from 
// https://www.fluentcpp.com/2019/05/28/better-macros-better-flags/)
#define MYPROJ_IS_BITNESS( X ) MYPROJ_IS_BITNESS_PRIVATE_DEFINITION_##X()

// Bitness checks borrowed from https://stackoverflow.com/a/12338526/201787
#if _WIN64 || ( __GNUC__ && __x86_64__ )
#    define MYPROJ_IS_BITNESS_PRIVATE_DEFINITION_64() 1
#    define MYPROJ_IS_BITNESS_PRIVATE_DEFINITION_32() 0
#    define MYPROJ_IF_64_BIT_ELSE( x64, x86 ) (x64)
    static_assert( sizeof( void* ) == 8, "Pointer size is unexpected for this bitness" );
#elif _WIN32 || __GNUC__
#    define MYPROJ_IS_BITNESS_PRIVATE_DEFINITION_64() 0
#    define MYPROJ_IS_BITNESS_PRIVATE_DEFINITION_32() 1
#    define MYPROJ_IF_64_BIT_ELSE( x64, x86 ) (x86)
    static_assert( sizeof( void* ) == 4, "Pointer size is unexpected for this bitness" );
#else
#    error "Unknown bitness!"
#endif

Dann können Sie es wie folgt verwenden:

#if MYPROJ_IS_BITNESS( 64 )
    DoMy64BitOperation()
#else
    DoMy32BitOperation()
#endif

Oder mit dem zusätzlichen Makro, das ich hinzugefügt habe:

MYPROJ_IF_64_BIT_ELSE( DoMy64BitOperation(), DoMy32BitOperation() );
Metall
quelle
0

Ich füge diese Antwort als Anwendungsfall und vollständiges Beispiel für die in einer anderen Antwort beschriebene Laufzeitprüfung hinzu .

Dies ist der Ansatz, den ich gewählt habe, um dem Endbenutzer zu vermitteln, ob das Programm als 64-Bit oder 32-Bit (oder in einem anderen Fall) kompiliert wurde:

version.h

#ifndef MY_VERSION
#define MY_VERSION

#include <string>

const std::string version = "0.09";
const std::string arch = (std::to_string(sizeof(void*) * 8) + "-bit");

#endif

test.cc

#include <iostream>
#include "version.h"

int main()
{
    std::cerr << "My App v" << version << " [" << arch << "]" << std::endl;
}

Kompilieren und testen

g++ -g test.cc
./a.out
My App v0.09 [64-bit]
vallismortis
quelle