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++ |