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