Determinación de 32 vs 64 bit en C ++

Estoy buscando una forma confiable de determinar si el código C ++ se está comstackndo en 32 vs 64 bit. Hemos encontrado lo que pensamos que es una solución razonable al usar macros, pero teníamos curiosidad por saber si la gente podía pensar en casos en los que esto podría fallar o si hay una mejor manera de hacerlo. Tenga en cuenta que estamos tratando de hacer esto en un entorno multiplataforma y comstackdor múltiple.

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

Gracias.

    Lamentablemente, no existe una macro multiplataforma que defina 32/64 bits en los principales comstackdores. He encontrado que la manera más efectiva de hacer esto es lo siguiente.

    Primero elijo mi propia representación. Prefiero ENVIRONMENT64 / ENVIRONMENT32. Luego descubro qué hacen todos los comstackdores principales para determinar si se trata de un entorno de 64 bits o no y lo uso para establecer mis 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 

    Otra ruta más fácil es simplemente establecer estas variables desde la línea de comandos del comstackdor.

     template 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(); } int main() { // appropriate function will be selected at compile time DoMyOperation(); return 0; } 

    Desafortunadamente, en un entorno multiplataforma de comstackdor cruzado, no existe un único método confiable para hacerlo solo en tiempo de comstackción.

    • Ambos _WIN32 y _WIN64 a veces pueden estar indefinidos, si la configuración del proyecto es defectuosa o está dañada (especialmente en Visual Studio 2008 SP1).
    • Un proyecto etiquetado como “Win32” podría configurarse en 64 bits, debido a un error de configuración del proyecto.
    • En Visual Studio 2008 SP1, a veces el intellisense no atenúa las partes correctas del código, de acuerdo con el #define actual. Esto hace que sea difícil ver exactamente qué #define se está utilizando en tiempo de comstackción.

    Por lo tanto, el único método confiable es combinar 3 controles simples :

    • 1) Configuración del tiempo de comstackción , y;
    • 2) comprobación de tiempo de ejecución , y;
    • 3) Comprobación robusta del tiempo de comstackción .

    Verificación simple 1/3: configuración del tiempo de comstackción

    Elija cualquier método para establecer la variable #define requerida. Sugiero el método 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 

    Comprobación simple 2/3: comprobación del tiempo de ejecución

    En main (), comprueba dos veces si sizeof () tiene sentido:

     #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 

    Comprobación simple 3/3: Comprobación robusta del tiempo de comstackción

    La regla general es “cada #define debe terminar en #else que genera un error”.

     #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 

    Actualización 2017-01-17

    Comentario de @AI.G :

    4 años después (no sé si fue posible antes) puede convertir el control en tiempo de ejecución al tiempo de comstackción utilizando static assert: static_assert (sizeof (void *) == 4) ;. Ahora todo está hecho en tiempo de comstackción 🙂

    Apéndice A

    Incidentalmente, las reglas anteriores se pueden adaptar para hacer que toda su base de código sea más confiable:

    • Cada instrucción if () termina en un “else” que genera una advertencia o error.
    • Cada instrucción switch () finaliza en un “valor predeterminado:” que genera una advertencia o error.

    La razón por la que esto funciona bien es porque te obliga a pensar en cada caso por adelantado y no confiar en la lógica (a veces defectuosa) en la parte “else” para ejecutar el código correcto.

    Utilicé esta técnica (entre muchas otras) para escribir un proyecto de 30,000 líneas que funcionó impecablemente desde el día en que se implementó por primera vez en la producción (eso fue hace 12 meses).

    Debería poder usar las macros definidas en stdint.h . En particular, INTPTR_MAX es exactamente el valor que necesita.

     #include  #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 

    Algunas (¿todas?) Versiones del comstackdor de Microsoft no vienen con stdint.h . No estoy seguro de por qué, ya que es un archivo estándar. Aquí hay una versión que puede usar: http://msinttypes.googlecode.com/svn/trunk/stdint.h

    Eso no funcionará en Windows para empezar. Longs y ints son ambos 32 bits ya sea que esté comstackndo para ventanas de 32 bits o de 64 bits. Creo que comprobar si el tamaño de un puntero es de 8 bytes es probablemente una ruta más confiable.

    Podrías hacer esto:

     #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 

    “Comstackdo en 64 bits” no está bien definido en C ++.

    C ++ establece solo límites inferiores para tamaños como int, long y void * . No hay garantía de que int sea de 64 bits, incluso cuando se comstack para una plataforma de 64 bits. El modelo permite, por ejemplo, 23 bit int s y sizeof(int *) != sizeof(char *)

    Existen diferentes modelos de progtwigción para plataformas de 64 bits.

    Su mejor apuesta es una prueba específica de la plataforma. Su segunda mejor decisión portátil debe ser más específica en lo que es 64 bits.

    La gente ya sugirió métodos que intentarán determinar si el progtwig se está comstackndo en 32-bit o 64-bit .

    Y quiero agregar que puede usar la característica c ++ 11 static_assert para asegurarse de que la architecture es lo que cree que es (“relajar”).

    Entonces, en el lugar donde defines las macros:

     #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 

    Su enfoque no estaba muy lejos, pero solo está verificando si long e int son del mismo tamaño. Teóricamente, ambos podrían ser de 64 bits, en cuyo caso su comprobación fallaría, suponiendo que ambos son 32 bits. Aquí hay un cheque que realmente verifica el tamaño de los tipos en sí, no su tamaño relativo:

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

    En principio, puede hacer esto para cualquier tipo para el que tenga una macro definida por el sistema con el valor máximo.

    Tenga en cuenta que el estándar requiere una long long de al menos 64 bits, incluso en sistemas de 32 bits.

    El siguiente código funciona bien para la mayoría de los entornos actuales:

      #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 

    Si puede usar configuraciones de proyectos en todos sus entornos, eso facilitaría la definición de un símbolo de 64 y 32 bits. Entonces tendrías configuraciones de proyecto como esta:

    Depuración de 32 bits
    Versión de 32 bits
    Depuración de 64 bits
    Versión de 64 bits

    EDITAR: Estas son configuraciones genéricas, no configuraciones dirigidas. Llámalos como quieras.

    Si no puedes hacer eso, me gusta la idea de Jared.

    Pondría las fonts de 32 bits y de 64 bits en diferentes archivos y luego seleccioné los archivos fuente apropiados usando el sistema de comstackción.