c++ - instalar - #ifdef para plataforma de 32 bits
instalar mingw 64 bits (11)
En una aplicación que mantengo, hemos encontrado un problema con las limitaciones del descriptor de archivos que afectan a stdlib. Este problema solo afecta a la versión de 32 bits de la biblioteca estándar.
He ideado una solución para mi código y me gustaría implementarlo, pero solo cuando se compila para un ejecutable de 32 bits. ¿Qué símbolo de preprocesador puedo #ifdef para determinar si el código se está compilando para un destino de 32 o 64 bits?
EDITAR
Lo sentimos, no mencioné, el código es multiplataforma, linux, windows, solaris y algunos otros sabores de Unix, principalmente con GCC para compilación. ¿Algún estándar de facto puedo usar multiplataforma?
Editar 2
He encontrado algunas definiciones "__ILP23" y "__LP64" que parece que pueden funcionar ... una discusión here explica los antecedentes de la plataforma Unix. ¿Alguien ha tenido alguna experiencia con el uso de estos define? ¿Será esto utilizable?
Creo que la definición es _WIN64
Depende de su sistema operativo y compilador, esas son decisiones de implementación.
Echa un vistazo a eso:
Lo probaría indirectamente, a través de la constante de valor máximo del puntero:
#include <stdint.h>
#if UINTPTR_MAX == 0xffFFffFF
// 32-bit platform
#elif UINTPTR_MAX == 0xffFFffFFffFFffFF
// 64-bit platform
#else
#error Unknown platform - does not look either like 32-bit or 64-bit
#endif
De esta manera, no confía en ninguna definición de plataforma específica para la arquitectura, sino en la consecuencia directa de tener una arquitectura específica: el tamaño del puntero.
Lo que probablemente terminaría haciendo es dentro de un Makefile, determinar si estás en una plataforma de 32 bits o de 64 bits usando uname. Luego, agregue a su CFLAGS, -DX32 o -DX64. Que solo podrías #ifdef X64.
Pero esto es solo una solución unixy. No estoy seguro de lo que haría en las ventanas.
No estoy seguro de si existe un #if def universal que sea apropiado. El estándar de C ++ es casi seguro que no define uno. Sin embargo, hay plataformas específicas.
Por ejemplo, windows
#if _WIN64
// 64 bit build
#else
// 32 bit build
#endif
EDIT OP mencionó que esta es una compilación cruzada entre Windows y no Windows usando GCC y otros compiladores
No existe una macro universal que pueda usarse para todas las plataformas y compiladores. Un poco de magia preprocesadora puede hacer el truco. Asumiendo que solo estás trabajando en chips x86 y amd64, lo siguiente debería hacer el truco. Aunque se puede expandir fácilmente para otras plataformas
#if _WIN64 || __amd64__
#define PORTABLE_64_BIT
#else
#define PORTABLE_32_BIT
#endif
No existe tal símbolo definido por el estándar de C ++; su plataforma específica (que no ha especificado en su pregunta) puede proporcionar uno.
Puede verificar un tipo conocido para su tamaño, por ejemplo, sizeof (int *) == 4 para una plataforma de 32 bits.
Como se conoce el tamaño de compiletime, creo que
if(sizeof(int*) == 4)
{
...
}
debería hacer el truco
Edición: los comentarios son correctos, necesita usar un regular si, #if no funciona.
Si está utilizando C ++, puede crear un código con plantilla y dejar que el compilador elija la especialización para usted basándose en la llamada sizeof (). Si construyes para una plataforma de 32 bits, el compilador solo instanciará el código para la plataforma de 32 bits. Si construyes para una plataforma de 654 bits, el compilador solo instanciará el código para la plataforma de 64 bits.
Recomiendo marcar el prefijo de SourceForge . No hay una sola respuesta, pero ciertamente puede ayudarlo a comenzar.
EDITAR: Para el código solo de GCC, puede usar __i386__
para verificar los chips x86 de 32 bits, y sugiero probar con __X86_64__
o algo similar para verificar los chips x86 de 64 bits. (Nota: Me ha llamado la atención que la respuesta anterior que involucra a __ia86__
es en realidad un chip diferente, no un chip x86 de 64 bits. Esto solo demuestra mi falta de experiencia en hardware. Para aquellos con más conocimientos de hardware que yo, consulte el SourceForge página sobre macros predefinidas a las que me vinculo anteriormente. Es mucho más precisa que yo. Hay otras que podrían funcionar, pero esas dos deberían ser bastante universales entre las versiones de GCC.
Solaris de al menos 32 bits tiene un límite de 256 punteros a archivos porque la estructura almacena el descriptor de archivos en un campo de caracteres sin firma. Esto se mantiene por compatibilidad con versiones anteriores de algunas versiones casi imposibles de SunOS. Otras plataformas: estoy tentado de decir que la mayoría de las demás plataformas no comparten esa limitación. Por otro lado, es relativamente inusual que un programa de usuario ordinario necesite que muchos archivos se abran simultáneamente; más a menudo indica un error (que no cierra los archivos cuando termina con ellos) que no. Sin embargo, dicho esto, puede ser un problema para cosas como servidores de bases de datos que necesitan tener muchos archivos de datos abiertos al mismo tiempo.
Un comentario dice:
Eso es casi todo. No tenemos una gran cantidad de archivos abiertos, pero el servidor maneja una gran cantidad de conexiones de clientes. Los manejadores de sockets y los descriptores de archivos parecen provenir del mismo lugar. Cuando tenemos muchas conexiones, ''fopen'' falla porque la llamada a nivel del sistema regresa y fd> 255.
Los ''manejadores de sockets'' son descriptores de archivos en el nivel de llamadas del sistema, por lo que vienen del mismo lugar que los descriptores de archivos normales para archivos.
Si tiene que solucionar esto, entonces debe ajustar su código de apertura del socket actual para que, si obtiene un descriptor de archivo en el rango 0..255, llame a '' dup2()
'' para crear un descriptor de archivo en el rango ese stdio no utilizará, y luego cierre el descriptor de archivo original. El único inconveniente de esto es que debe realizar un seguimiento de los descriptores de archivo disponibles, ya que dup2
cerrará alegremente el descriptor del archivo de destino si está actualmente abierto.
Por supuesto, asumo que su código de socket lee descriptores de archivo y no punteros de archivo. Si ese es el caso, tiene problemas más grandes: muchas cosas quieren usar los mismos recursos y no todos pueden usarlos al mismo tiempo.
Yo uso una construcción como esta para Windows:
#if defined(_WIN64) //64-bit code #elif defined(_M_IX86) //32-bit code #else #error "Unknown platform" #endif
Versus:
#if defined(_WIN64) // 64 bit code #else // 32-bit code #endif
En la solución anterior, debido al # error, el compilador podrá decirle dónde necesita agregar código para una nueva plataforma. Esto ayuda a la capacidad de mantenimiento si alguna vez se encuentra con una plataforma que no sea de 64 bits ni de 32 bits. Sí, _M_IX86 no es exactamente sinónimo de 32 bits, pero creo que la única plataforma de 32 bits que la mayoría de nosotros soportamos es, de hecho, x86. Así que como medida práctica basta.
En la solución posterior, tendrá que averiguar manualmente dónde necesita el código para su nueva plataforma utilizando grep o algo así. Esto es tedioso y propenso a errores.
Se me ocurre que la siguiente construcción también sería aceptable, aunque no la he probado en producción ni realmente lo he pensado mucho.
#if defined(_WIN64) //64-bit code #elif defined(_WIN32) //32-bit code #else #error "Unknown platform" #endif