Which Cross Platform Preprocessor Defines? (__WIN32__ or __WIN32 or WIN32 )?

77,227

Solution 1

It depends what you are trying to do. You can check the compiler if your program wants to make use of some specific functions (from the gcc toolchain for example). You can check for operating system ( _WINDOWS, __unix__ ) if you want to use some OS specific functions (regardless of compiler - for example CreateProcess on Windows and fork on unix).

Macros for Visual C

Macros for gcc

You must check the documentation of each compiler in order to be able to detect the differences when compiling. I remember that the gnu toolchain(gcc) has some functions in the C library (libc) that are not on other toolchains (like Visual C for example). This way if you want to use those functions out of commodity then you must detect that you are using GCC, so the code you must use would be the following:

#ifdef __GNUC__
// do my gcc specific stuff
#else
// ... handle this for other compilers
#endif

Solution 2

This article answers your question:

The article is quite long, and includes tables that are hard to reproduce, but here's the essence:

You can detect Unix-style OS with:

#if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__)))
    /* UNIX-style OS. ------------------------------------------- */

#endif

Once you know it's Unix, you can find if it's POSIX and the POSIX version with:

#include <unistd.h>
#if defined(_POSIX_VERSION)
    /* POSIX compliant */
#endif

You can check for BSD-derived systems with:

#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
#include <sys/param.h>
#if defined(BSD)
    /* BSD (DragonFly BSD, FreeBSD, OpenBSD, NetBSD). ----------- */

#endif
#endif

and Linux with:

#if defined(__linux__)
    /* Linux  */
#endif

and Apple's operating systems with

#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

Windows with Cygwin

#if defined(__CYGWIN__) && !defined(_WIN32)
    /* Cygwin POSIX under Microsoft Windows. */
#endif

And non-POSIX Windows with:

#if defined(_WIN64)
    /* Microsoft Windows (64-bit) */
#elif defined(_WIN32)
    /* Microsoft Windows (32-bit) */
#endif

The full article lists the following symbols, and shows which systems define them and when: _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 related article (archive.org link) covers detecting compilers and compiler versions. It lists the following symbols: __clang__, __GNUC__, __GNUG__, __HP_aCC, __HP_cc, __IBMCPP__, __IBMC__, __ICC, __INTEL_COMPILER, _MSC_VER, __PGI, __SUNPRO_C, __SUNPRO_CC for detecting compilers, and __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__ for detecting compiler versions.

Solution 3

Don't see why you have to. You might have to remember to specify the definition manually on your compiler's commandline, but that's all. For the record, Visual Studio's definition is _WIN32 (with one underscore) rather than __WIN32. If it's not defined then it's not defined, and it won't matter.

Solution 4

I've rebuild my answer... Damn, editing berserk :P:

You don't need to use partical one. And probably for MacOSX, Linux and other Unix-likes you don't need to use any at all.

Most popular one is (as far as Google tells the truth) is _WIN32.

You never define it "by hand" in your source code. It is defined in one of these ways:
as a commandline preprocessor/compiler flag (like g++ -D _WIN32)
or it is predefined by compiler itself (most of Windows compilers predefine _WIN32, and sometimes other like WIN32 or _WIN32_ too. -- Then you don't need to worry about defining it at all, compiler does the whole work.


And my old answer:

You don't 'have to' anything. It's just for multi-platform compatibility. Often version of code for all Unix-likes (including Linux, MacOSX, BSD, Solaris...) and other POSIX platform will be completely the same and there must be some changes for Windows. So people write their code generally for Unix-likes and put some Windows-only (eg. DirectX instructions, Windows-like file paths...) parts between #ifdef _WIN32 and #endif.

If you have some parts eg. X-Window-system only, or MacOS-only, you do similar with something like #ifdef X_WINDOW or #ifdef MACOS. Then, you need set a proper preprocessor definition while compiling (with gcc using -D flag, like eg. gcc -D _WIN32).

If you don't write any platform-dependent code, then you don't need to care for such a #ifdef, #else, #endif blocks. And most of Windows compilers/preprocessors AFAIK have predefined some symbols like _WIN32 (most popular, as far as google tells the truth), WIN32, _WIN32_, etc. So compiling it on Windows most probably you don't need to make anything else than just compiling.

Share:
77,227
math
Author by

math

Updated on June 15, 2020

Comments

  • math
    math almost 4 years

    I often see __WIN32, WIN32 or __WIN32__. I assume that this depends on the used preprocessor (either one from visual studio, or gcc etc).

    Do I now have to check first for os and then for the used compiler? We are using here G++ 4.4.x, Visual Studio 2008 and Xcode (which I assume is a gcc again) and ATM we are using just __WIN32__, __APPLE__ and __LINUX__.

  • math
    math almost 14 years
    So I could write the #ifdef __WIN32__ only once and not #ifdef WIN32 || __WIN32 || __WIN32__
  • math
    math almost 14 years
    Probably my question is very unclear: I don't want to define WIN32 but to use it with #ifdef. And I wondered why there are so many variants and if there is one which should work with most of the compiliers.
  • silmeth
    silmeth almost 14 years
    As I said, people just use what they like, there is no standard. Anyway, you can define it when compiling yourself in commandline (and also in IDE options, etc.), so using "unsupported" WIN32__ instead of "good" _WIN32 isn't a problem. And, as I said, most compilers support _WIN32 and some support many others (mingw support WIN32 _WIN32 WIN32 __WIN32 MINGW32 WINNT WINNT __WINNT). See this one: stackoverflow.com/questions/142508/…
  • INS
    INS almost 14 years
    You can create wrappers for different behaviors and use those wrappers. This way you deal with platform/compiler differences in just a few source files, which is (in my opinion) better that dealing with makefiles for each platform.
  • Billy ONeal
    Billy ONeal almost 14 years
    @brubelsabs: Yes, but you'd have to remember to put in the preprocessor definition yourself on the commandline if you decided to use another compiler.
  • Chris K
    Chris K almost 14 years
    You have a valid point. However, I can't conceive of a situation where you're supporting multiple platforms and aren't using Makefiles of some sort (gmake/cmake/qmake) anyway. Windows library definitions to link.exe are not the same as gcc -L -l. Nor are compiler optimization settings. I'd much rather deal with my platform flags in one Makefile (or a few by inclusion) than have to remember to include platform_magic.h in every header/source file. Boost does it your way - in boost/system/config.hpp it determines what platform it's running on. We'll just have to agree to disagree. :-D
  • rubenvb
    rubenvb about 13 years
    AFAIK _WIN32 is defined for all (modern) Windows compilers (excluding WinCE of course). No need to define it yourself...
  • IInspectable
    IInspectable over 9 years
    @math: Your #ifdef-expression is wrong. It should be #if defined(WIN32) || defined(__WIN32) || defined(__WIN32__). See C Preprocessor directives and boolean operators for reference.
  • math
    math over 9 years
    Links might get broken, and I just posting the link without any explanation I consider not a good QA style. Even it when this would be just a comment. Please try to sum up the article.
  • Charphacy
    Charphacy over 9 years
    Good call. I've updated the article to give much more detail, and also provide links to archive.org to better handle the site vanishing.
  • Ben Voigt
    Ben Voigt over 9 years
    @IInspectable: Or perhaps #if WIN32 || _WIN32 || __WIN32__. Undefined names are treated as zero. The question is what should be done in case of #define _WIN32 0.
  • IInspectable
    IInspectable over 9 years
    @Ben: You have already answered, why your proposed #if-expression is inappropriate. If you want to check whether a preprocessor symbol is defined, it is best to check whether a preprocessor symbol is defined.
  • Ben Voigt
    Ben Voigt over 9 years
    @IInspectable: But why do you think it is more appropriate to treat #define _WIN32 0 the same as #define _WIN32 1, rather than #undef _WIN32 ?
  • IInspectable
    IInspectable over 9 years
    @Ben: Because that is how it is specified and documented. Predefined Macros: "_WIN32 Defined for applications for Win32 and Win64."