These are the predefined macros that C/C++ compilers define to tell you what type of processor the target processor, for which code is being generated, is. There are also predefined macros in C/C++ that tell you the compiler, predefined macros in C/C++ that tell you the target platform and predefined macros in C/C++ that tell you what language features are available.
Macro | Definition | Compiler(s) |
---|---|---|
Macro | Definition | Compiler(s) |
__32BIT__ |
The target processor is (nominally) 32-bit. | IBM VAC++ |
__64BIT__ |
The target processor is (nominally) 64-bit. | |
__FLT_HAS_INFINITY__ |
Defined to 1 if and only if the float type has a value for representing
infinity.
|
GCC |
__FLT_HAS_QUIET_NAN__ |
Defined to 1 if and only if the float type has a non-signalling (quiet) Not A
Number value.
|
GCC |
__LDBL_HAS_INFINITY__ |
Defined to 1 if and only if the long double type has a value for representing
infinity.
|
GCC |
__LDBL_HAS_QUIET_NAN__ |
Defined to 1 if and only if the long double type has a non-signalling (quiet) Not A
Number value.
|
GCC |
__ORDER_LITTLE_ENDIAN__ |
Defined to an unspecified non-zero integer value distinct from the other two order macros. | GCC |
__ORDER_BIG_ENDIAN__ |
Defined to an unspecified non-zero integer value distinct from the other two order macros. | GCC |
__ORDER_PDP_ENDIAN__ |
Defined to an unspecified non-zero integer value distinct from the other two order macros. | GCC |
__BYTE_ORDER__ |
Defined to be equal in value to one of
__ORDER_LITTLE_ENDIAN__ ,
__ORDER_BIG_ENDIAN__ , or
__ORDER_PDP_ENDIAN__ ;
indicating the order of bytes within integer types.
|
GCC |
__FLOAT_WORD_ORDER__ |
Defined to be equal in value to one of
__ORDER_LITTLE_ENDIAN__ ,
__ORDER_BIG_ENDIAN__ , or
__ORDER_PDP_ENDIAN__ ;
indicating the order of bytes within floating point types.
|
GCC |
The point of the order macros is that they enable feature tests of the form:
#if __BYTE_ORDER__ && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) // ... little-endian code #endif
The fact that they are non-zero when defined means that you can employ the zero value case to determine whether the feature test is available in the first place. The C++ language standard mandates that the value of an identifier that isn't a macro, in a controlling expression for conditional compilation, is zero, remember.
Macro | Definition | Compiler(s) |
---|---|---|
Macro | Definition | Compiler(s) |
__IA64__ |
Defined to 1 if the processor architecture is IA-64 (a.k.a. Itanium). | GCC |
__ia64__ |
Defined to 1 if the processor architecture is IA-64 (a.k.a. Itanium). | GCC |
_M_IA64 |
Defined to 1 if the processor architecture is IA-64 (a.k.a. Itanium). | MSVC++ |
_M_X64 |
Defined if a 64-bit x86 instruction set is the target. | MSVC++ |
__X86_64__ |
Defined to 1 if a 64-bit x86 instruction set is the target. | OpenWatcom |
__x86_64__ |
Defined if a 64-bit x86 instruction set is the target. | GCC, Clang, Intel |
_M_IX86 |
Defined if a 16-bit or a 32-bit 8086 or 80x86 processor is the target. The value indicates the processor but not the bitness: 0 for 8086, 100 for 80186, 200 for 80286, 300 for 80386, 400 for 80486, 500 for Pentium, and 600 for Pentium Pro or later. | OpenWatcom |
Defined if and only if a 32-bit 80x86 processor is the target. The value indicates the processor: 300 for 80386, 400 for 80486, 500 for Pentium, and 600 for Pentium Pro or later. | MSVC++, DigitalMars | |
__X86__ |
Defined to 1 if a 16-bit or 32-bit x86 instruction set is the target. | OpenWatcom |
__386__ |
Defined to 1 if and only if a 32-bit x86 instruction set is the target. | OpenWatcom |
_M_I386 |
||
__I86__ |
Defined to 1 if and only if a 16-bit x86 instruction set is the target. | OpenWatcom |
Always defined. The value indicates the processor but not the bitness: 0 for 8086, 1 for 80186, 2 for 80286, 3 for 80386, 4 for 80486, 5 for Pentium, and 6 for Pentium Pro or later. | DigitalMars | |
_M_I86 |
Defined to 1 if and only if a 16-bit x86 instruction set is the target. | OpenWatcom |
Always defined. | DigitalMars | |
__i386 |
Defined if a 32-bit x86 instruction set is the target. | Intel |
__i386__ |
Defined if a 32-bit x86 instruction set is the target. | GCC, Intel |
_M_I8086 |
Defined if 16-bit 8086 code is the target. | DigitalMars |
_M_I286 |
Defined to 1 if and only if an 80286 or later x86 or x86-64 processor is the target. | DigitalMars |
A consistent, robust, and portable way to differentiate amongst the different Intel Architecture targets is tricky.
OpenWatcom provides a simple differentiation. Its compiler for 16-bit targets
defines __I86__
and _M_I86
, and its compiler for
32-bit targets defines __386__
and _M_I386
. Both
compilers define __X86__
and _M_IX86
, with the
latter indicating what instruction set is being used.
(Remember that the new instructions specific to the 80486 and Pentium are
available in both 16-bit and 32-bit code.)
This would be a fairly straightforward scheme:
// This is OpenWatcom's scheme. #if __X86_64__ // It's the x86-64/IA32e architecture. #elif __X86__ // It's an x86 architecture of some kind: # if __386__ || _M_I386 // Using the compiler for 32-bit targets, wpp386 or wcc386, so must be x86-32. # if _M_IX86 >= 600 // Pentium Pro instructions and instruction scheduling # elif _M_IX86 >= 500 // Pentium instructions and instruction scheduling # elif _M_IX86 >= 400 // 80486 instructions and instruction scheduling # elif _M_IX86 >= 300 // 80386 instructions and instruction scheduling # else // This is not possible with the 32-bit compiler. # endif # elif __I86__ || _M_I86 // Using the compiler for 16-bit targets, wpp or wcc, so must be x86-16. # if _M_IX86 >= 600 // Pentium Pro instructions and instruction scheduling # elif _M_IX86 >= 500 // Pentium instructions and instruction scheduling # elif _M_IX86 >= 400 // 80486 instructions and instruction scheduling # elif _M_IX86 >= 300 // 80386 instructions and instruction scheduling # elif _M_IX86 >= 200 // 80286 instructions and instruction scheduling # elif _M_IX86 >= 100 // 80186 instructions and instruction scheduling # else // 8086 instructions and instruction scheduling # endif # endif #endif
That is, it would be simple, if everyone else followed the same scheme.
But they don't. DigitalMars always defines the _M_I86
macro, even for 32-bit targets, and doesn't define __386__
or
_M_I386
at all. DigitalMars doesn't support anything other than
16-bit and 32-bit targets:
// This is DigitalMars' scheme. #if defined(_M_IX86) // It must be the x86-32 architecture. # if _M_IX86 >= 600 // Pentium Pro instructions and instruction scheduling # elif _M_IX86 >= 500 // Pentium instructions and instruction scheduling # elif _M_IX86 >= 400 // 80486 instructions and instruction scheduling # elif _M_IX86 >= 300 // 80386 instructions and instruction scheduling # else // This is not possible with the 32-bit compiler. # endif #else // It must be the x86-16 architecture. # if _M_I286 // 80286 instructions and instruction scheduling # elif _M_I8086 // 8086 instructions and instruction scheduling # else // This is not possible with the 16-bit compiler. # endif #endif
Microsoft's C++ compiler, similarly, doesn't define
__I86__
, _M_I86
, __386__
, or
_M_I386
at all, and only defines _M_IX86
.
Since Microsoft's C++ compiler doesn't even allow for the possibility
of 16-bit targets, is scheme is somewhat different:
// This is Microsoft's scheme. #if _M_IA64 // It's the Itanium/IA64 architecture. #elif _M_X64 /*Modern macro*/ \ || _M_AMD64 /*Older macro with a vendor-specific name*/ // It's the x86-64 architecture. #elif _M_IX86 // It's the x86-32 architecture. # if _M_IX86 >= 600 // Pentium Pro instructions and instruction scheduling # elif _M_IX86 >= 500 // Pentium instructions and instruction scheduling # elif _M_IX86 >= 400 // 80486 instructions and instruction scheduling # elif _M_IX86 >= 300 // 80386 instructions and instruction scheduling # else // This is not possible with the 32-bit compiler. # endif #else // … _M_PPC, _M_RX000, and _M_ALPHA indicate non-Intel // architectures that are no longer available as targets. #endif
Worse, GCC, Clang, and Intel's C++ compiler don't define any of these nine macros. Instead, they have an alternative scheme of their own, using a completely disjoint set of macros (note the lowercase spellings instead of uppercase) that are — just to make the incompatibility symmetrical — not defined at all by OpenWatcom, Microsoft's C++ compiler, or DigitalMars:
// This is the scheme for GCC, Clang, and Intel's compiler. #if defined(__ia64__) // ... Itanium/IA64 #if defined(__x86_64__) // ... x86-64/IA32e #elif defined(__i386__) // ... x86-32 #endif
Combining these into a single, portable, conditional compilation that works on all of the compilers makes quite a mess:
#if defined(__IA64__) \ || _M_IA64 /*MSVC++*/ \ || defined(__ia64__) /*GCC,Clang,Intel*/ // ... Itanium/Intel Architecture 64 #elif __X86_64__ /*OpenWatcom*/ \ || _M_X64 /*MSVC++*/ \ || _M_AMD64 /*MSVC++ compatibility with older compilers*/ \ || defined(__x86_64__) /*GCC,Clang,Intel*/ // ... x86-64/IA32e #elif __386__ || _M_I386 /*OpenWatcom*/ \ || (defined(__DMC__) && defined(_M_IX86)) /*DigitalMars*/ \ || (defined(_MSC_VER) && _M_IX86) /*MSVC++*/ \ || defined(__i386__) /*GCC,Clang,Intel*/ // ... x86-32 # if _M_IX86 >= 600 // Pentium Pro instructions and instruction scheduling # elif _M_IX86 >= 500 // Pentium instructions and instruction scheduling # elif _M_IX86 >= 400 // 80486 instructions and instruction scheduling # elif _M_IX86 >= 300 // 80386 instructions and instruction scheduling # else // This must be GCC or Clang. # endif # elif __I86__ || _M_I86 /*OpenWatcom*/ \ || (defined(__DMC__) && !defined(_M_IX86)) /*DigitalMars*/ // ... x86-16 # if _M_IX86 >= 600 // Pentium Pro instructions and instruction scheduling # elif _M_IX86 >= 500 // Pentium instructions and instruction scheduling # elif _M_IX86 >= 400 // 80486 instructions and instruction scheduling # elif _M_IX86 >= 300 // 80386 instructions and instruction scheduling # elif _M_IX86 >= 200 || _M_I286 // 80286 instructions and instruction scheduling # elif _M_IX86 >= 100 // 80186 instructions and instruction scheduling # else // 8086 instructions and instruction scheduling # endif #endif
Macro | Definition | Compiler(s) |
---|---|---|
Macro | Definition | Compiler(s) |
__ppc__ |
Defined to 1 if the processor architecture is PowerPC | GCC |
_M_PPC |
Defined to 1 if the processor architecture is PowerPC (no longer available as a target in modern revisions of the compiler) | MSVC++ |
_M_RX000 |
Defined to 1 if the processor architecture is MIPS (no longer available as a target in modern revisions of the compiler) | MSVC++ |
_M_ALPHA |
Defined to 1 if the processor architecture is Alpha (no longer available as a target in modern revisions of the compiler) | MSVC++ |