There’s confusion between user-defined and predefined Windows 32/64-bit operating-system identification macros. Matthew Wilson shines light on the issue.
TL;DR:
Compiler defines
_WIN32
and
_WIN64
. You define
WIN32
or
WIN64
. Carefully discriminate.
Bite:
When compiling for Windows 32 and 64-bit architectures, there are four preprocessor object-like macro definitions for discriminating operating system that one may encounter:
-
_WIN32
-
_WIN64
-
WIN32
-
WIN64
You must take care that you understand the origins and meanings of these.
_WIN32 and WIN64
The symbol
_WIN32
is defined
by the compiler
to indicate that this is a (32bit) Windows compilation. Unfortunately, for historical reasons, it is also defined for 64-bit compilation.
The symbol
_WIN64
is defined
by the compiler
to indicate that this is a 64-bit Windows compilation.
Thus:
To identify unambiguously whether the compilation is 64-bit Windows, one tests only
_WIN64
as in:
#if defined(_WIN64) /* Is Windows 64-bit */ #else /* Is not Windows 64-bit */ #endif
To identify unambiguously whether the compilation is 32-bit Windows, one tests both
_WIN32
and
_WIN64
as in:
#if defined(_WIN32) && \ !defined(_WIN64) /* Is Windows 32-bit */ #else /* Is not Windows 32-bit */ #endif
To identify unambiguously whether the compilation is a form of Windows one tests both
_WIN32
and
_WIN64
as in:
#if defined(_WIN64) /* Is Windows 64-bit */ #elif defined(_WIN32) /* Is Windows 32-bit */ #else /* Not Windows */ #endif
WIN32 and WIN64
The symbol
WIN32
is defined by the user to indicate whatever the user chooses it to indicate. By convention, the definition of this symbol indicates a 32-bit Windows compilation, and nothing else! Microsoft (and other) tools generate projects with this symbol defined.
The symbol
WIN64
is defined by the user to indicate whatever the user chooses it to indicate. By convention, the definition of this symbol indicates a 64-bit Windows compilation, and nothing else!
When properly defined, these symbols can be used to indicate unambiguously the 32- and 64-bit Windows compilation contexts.
Caution with WIN32 / WIN64
Unfortunately, when duplicating a Win32 project to x64, the Microsoft Visual Studio wizards do not translate
WIN32
to
WIN64
. You must remember to do this yourself, in order for the inferences given above to hold. Do not add a separate
WIN64
to the x64 configuration settings: replace the existing
WIN32
with
WIN64
.
Why bother with WIN32 / WIN64 (and not simply rely on _WIN32 / _WIN64)?
There are doubtless many reasons. The reasons I adhere strictly to this are:
- it is a widely adopted and meaningful convention, so adheres to the principle of least surprise [ PoLS ].
- it facilitates the ability to emulate (parts of) other operating systems (e.g. UNIX [ UNIXem ]) while on Windows, which can be tremendously helpful when porting code.
References
[PoLS] The Art of UNIX Programming , Eric S. Raymond, AddisonWesley, 2003
[UNIXem] UNIXem is a simple, limited UNIXAPI emulation library for Windows. See http://synesis.com.au/software/unixem.html .