Matemáticas
a menudo veo __WIN32
, WIN32
o __WIN32__
. Supongo que esto depende del preprocesador utilizado (ya sea uno de Visual Studio o GCC, etc.).
¿Ahora tengo que verificar primero el sistema operativo y luego el compilador usado? Estamos usando aquí G ++ 4.4.x, Visual Studio 2008 y Xcode (que supongo que es un gcc nuevamente) y ATM que estamos usando solo __WIN32__
, __APPLE__
y __LINUX__
.
Charfacia
Este artículo responde a tu pregunta:
- Sugerencia de C/C++: Cómo detectar el tipo de sistema operativo usando macros predefinidas del compilador (más enlace archive.org en caso de que desaparezca).
El artículo es bastante largo e incluye tablas que son difíciles de reproducir, pero esta es la esencia:
Puede detectar un sistema operativo de estilo Unix con:
#if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__)))
/* UNIX-style OS. ------------------------------------------- */
#endif
Una vez que sepa que es Unix, puede encontrar si es POSIX y la versión POSIX con:
#include <unistd.h>
#if defined(_POSIX_VERSION)
/* POSIX compliant */
#endif
Puede buscar sistemas derivados de BSD con:
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
#include <sys/param.h>
#if defined(BSD)
/* BSD (DragonFly BSD, FreeBSD, OpenBSD, NetBSD). ----------- */
#endif
#endif
y Linux con:
#if defined(__linux__)
/* Linux */
#endif
y los sistemas operativos de Apple con
#if defined(__APPLE__) && defined(__MACH__)
/* Apple OSX and iOS (Darwin) */
#include <TargetConditionals.h>
#if TARGET_IPHONE_SIMULATOR == 1
/* iOS in Xcode simulator */
#elif TARGET_OS_IPHONE == 1
/* iOS on iPhone, iPad, etc. */
#elif TARGET_OS_MAC == 1
/* OS X */
#endif
#endif
Ventanas con Cygwin
#if defined(__CYGWIN__) && !defined(_WIN32)
/* Cygwin POSIX under Microsoft Windows. */
#endif
Y Windows no POSIX con:
#if defined(_WIN64)
/* Microsoft Windows (64-bit) */
#elif defined(_WIN32)
/* Microsoft Windows (32-bit) */
#endif
El artículo completo enumera los siguientes símbolos y muestra qué sistemas los definen y cuándo: _AIX
, __APPLE__
, __CYGWIN32__
, __CYGWIN__
, __DragonFly__
, __FreeBSD__
, __gnu_linux
, hpux
, __hpux
, linux
, __linux
, __linux__
, __MACH__
, __MINGW32__
, __MINGW64__
, __NetBSD__
, __OpenBSD__
, _POSIX_IPV6
, _POSIX_MAPPED_FILES
, _POSIX_SEMAPHORES
, _POSIX_THREADS
, _POSIX_VERSION
, sun
, __sun
, __SunOS
, __sun__
, __SVR4
, __svr4__
, TARGET_IPHONE_SIMULATOR
, TARGET_OS_EMBEDDED
, TARGET_OS_IPHONE
, TARGET_OS_MAC
, UNIX
, unix
, __unix
, __unix__
, WIN32
, _WIN32
, __WIN32
, __WIN32__
, WIN64
, _WIN64
, __WIN64
, __WIN64__
, WINNT
, __WINNT
, __WINNT__
.
A Artículo relacionado (enlace archive.org) cubre la detección de compiladores y versiones de compiladores. Enumera los siguientes símbolos: __clang__
, __GNUC__
, __GNUG__
, __HP_aCC
, __HP_cc
, __IBMCPP__
, __IBMC__
, __ICC
, __INTEL_COMPILER
, _MSC_VER
, __PGI
, __SUNPRO_C
, __SUNPRO_CC
para detectar compiladores, y __clang_major__
, __clang_minor__
, __clang_patchlevel__
, __clang_version__
, __GNUC_MINOR__
, __GNUC_PATCHLEVEL__
, __GNUC__
, __GNUG__
, __HP_aCC
, __HP_cc
, __IBMCPP__
, __IBMC__
, __ICC
, __INTEL_COMPILER
, __INTEL_COMPILER_BUILD_DATE
, _MSC_BUILD
, _MSC_FULL_VER
, _MSC_VER
, __PGIC_MINOR__
, __PGIC_PATCHLEVEL__
, __PGIC__
, __SUNPRO_C
, __SUNPRO_CC
, __VERSION__
, __xlC_ver__
, __xlC__
, __xlc__
para detectar versiones del compilador.
-
Los enlaces pueden romperse, y solo publico el enlace sin ninguna explicación que considero que no es un buen estilo de control de calidad. Incluso cuando esto sería sólo un comentario. Intenta resumir el artículo.
– Matemáticas
8 de octubre de 2014 a las 6:51
-
Buena llamada. Actualicé el artículo para brindar muchos más detalles y también proporcioné enlaces a archive.org para manejar mejor la desaparición del sitio.
– Charfacia
15/10/2014 a las 18:55
Depende de lo que estés tratando de hacer. Puede verificar el compilador si su programa quiere hacer uso de algunas funciones específicas (de la cadena de herramientas gcc, por ejemplo). Puede verificar el sistema operativo (_WINDOWS, __unix__) si desea usar algunas funciones específicas del sistema operativo (independientemente del compilador, por ejemplo, CreateProcess en Windows y bifurcación en Unix).
Debes consultar la documentación de cada compilador para poder detectar las diferencias a la hora de compilar. Recuerdo que la cadena de herramientas gnu (gcc) tiene algunas funciones en la biblioteca C (biblioteca) que no están en otras cadenas de herramientas (como Visual C, por ejemplo). De esta forma si quieres usar esas funciones por comodidad entonces debes detectar que estás usando GCC, por lo que el código que debes usar sería el siguiente:
#ifdef __GNUC__
// do my gcc specific stuff
#else
// ... handle this for other compilers
#endif
No veo por qué tienes que hacerlo. Es posible que deba recordar especificar la definición manualmente en la línea de comandos de su compilador, pero eso es todo. Para que conste, la definición de Visual Studio es _WIN32
(con un guión bajo) en lugar de __WIN32
. Si no está definido, entonces no está definido y no importará.
-
Entonces podría escribir el
#ifdef __WIN32__
solo una vez y no#ifdef WIN32 || __WIN32 || __WIN32__
– Matemáticas
7 de junio de 2010 a las 14:53
-
@brubelsabs: Sí, pero debe recordar ingresar la definición del preprocesador usted mismo en la línea de comandos si decide usar otro compilador.
– Billy ONeal
7 de junio de 2010 a las 16:09
-
hasta donde se
_WIN32
está definido para todos los compiladores (modernos) de Windows (excepto WinCE, por supuesto). No hace falta que lo definas tú mismo…– rubenvb
31 de enero de 2011 a las 19:43
-
@math: Tu
#ifdef
-La expresión es incorrecta. Debería ser#if defined(WIN32) || defined(__WIN32) || defined(__WIN32__)
. Consulte las directivas del preprocesador C y los operadores booleanos como referencia.– Inspeccionable
12/08/2014 a las 12:30
-
@IInspectable: O tal vez
#if WIN32 || _WIN32 || __WIN32__
. Los nombres no definidos se tratan como cero. La pregunta es qué se debe hacer en caso de#define _WIN32 0
.– Ben Voigt
15/10/2014 a las 18:58
silmet
Reconstruí mi respuesta… Maldición, editando loco :P:
No es necesario utilizar una partical. Y probablemente para MacOSX, Linux y otros similares a Unix, no necesita usar ninguno.
El más popular es (hasta donde Google dice la verdad) es _WIN32
.
Tú nunca defínalo “a mano” en su código fuente. Se define de una de estas formas:
como una marca de preprocesador/compilador de línea de comandos (como g++ -D _WIN32
)
o está predefinido por el propio compilador (la mayoría de los compiladores de Windows predefinen _WIN32
y a veces otras como WIN32
o _WIN32_
también. — Entonces no necesita preocuparse por definirlo en absoluto, el compilador hace todo el trabajo.
Y mi vieja respuesta:
No ‘tienes que’ nada. Es solo por compatibilidad multiplataforma. A menudo, la versión del código para todos los similares a Unix (incluidos Linux, MacOSX, BSD, Solaris…) y otras plataformas POSIX serán completamente iguales y debe haber algunos cambios para Windows. Por lo tanto, las personas escriben su código generalmente para los gustos de Unix y colocan algunas partes solo de Windows (por ejemplo, instrucciones de DirectX, rutas de archivos similares a Windows …) entre #ifdef _WIN32
y #endif
.
Si tiene algunas piezas, por ejemplo. Solo el sistema X-Window, o solo MacOS, haces algo similar con algo como #ifdef X_WINDOW
o #ifdef MACOS
. Luego, debe establecer una definición de preprocesador adecuada durante la compilación (con gcc usando el indicador -D, como por ejemplo. gcc -D _WIN32
).
Si no escribe ningún código dependiente de la plataforma, entonces no necesita preocuparse por tal #ifdef, #else, #endif
bloques Y la mayoría de los compiladores/preprocesadores de Windows AFAIK han predefinido algunos símbolos como _WIN32
(más popular, en la medida en que Google dice la verdad), WIN32
, _WIN32_
etc. Así que compilarlo en Windows lo más probable es que no necesite hacer nada más que simplemente compilar.
Suspiro, no confíe en nada del compilador, especifique para qué plataforma está construyendo en su Makefile. En pocas palabras, cualquier cosa que comience con _ depende de la implementación y no es portátil.
Probé su método una vez, en un proyecto muy grande, y entre Sun-C++ y GCC, decidimos ir con el control de Makefile en lugar de tratar de deducir qué iban a hacer los compiladores.
-
Puede crear contenedores para diferentes comportamientos y usar esos contenedores. De esta manera, se manejan las diferencias de plataforma/compilador en solo unos pocos archivos fuente, lo que (en mi opinión) es mejor que lidiar con archivos MAKE para cada plataforma.
– EN S
7 de junio de 2010 a las 15:23
-
Tienes un punto válido. Sin embargo, no puedo concebir una situación en la que admita múltiples plataformas y no esté utilizando archivos Make de algún tipo (gmake/cmake/qmake) de todos modos. Las definiciones de la biblioteca de Windows para link.exe no son las mismas que gcc -L -l. Tampoco lo son las configuraciones de optimización del compilador. Prefiero tratar con mis banderas de plataforma en un Makefile (o algunos por inclusión) que tener que recordar incluir platform_magic.h en cada encabezado/archivo fuente. Boost lo hace a su manera: en boost/system/config.hpp determina en qué plataforma se está ejecutando. Tendremos que estar de acuerdo en no estar de acuerdo. 😀
– Chris K.
7 de junio de 2010 a las 16:49
-
Puede crear contenedores para diferentes comportamientos y usar esos contenedores. De esta manera, se manejan las diferencias de plataforma/compilador en solo unos pocos archivos fuente, lo que (en mi opinión) es mejor que lidiar con archivos MAKE para cada plataforma.
– EN S
7 de junio de 2010 a las 15:23
-
Tienes un punto válido. Sin embargo, no puedo concebir una situación en la que admita múltiples plataformas y no esté utilizando archivos Make de algún tipo (gmake/cmake/qmake) de todos modos. Las definiciones de la biblioteca de Windows para link.exe no son las mismas que gcc -L -l. Tampoco lo son las configuraciones de optimización del compilador. Prefiero tratar con mis banderas de plataforma en un Makefile (o algunos por inclusión) que tener que recordar incluir platform_magic.h en cada encabezado/archivo fuente. Boost lo hace a su manera: en boost/system/config.hpp determina en qué plataforma se está ejecutando. Tendremos que estar de acuerdo en no estar de acuerdo. 😀
– Chris K.
7 de junio de 2010 a las 16:49
_WIN32
es sistemática, más a menudo que otras grafías. Ver sourceforge.net/p/predef/wiki/SistemasOperativos . La buena práctica es probar lo que es relevante en cada situación (SO, archi, compilador…) y no probar uno por el otro. Y tampoco redefinir el tuyo propio.– Sandburg
10 de enero de 2019 a las 8:41