Many times we are developing portable programs with C++ that we need to create a single code that works on different platforms.
And for that we need to use PRE PROCESSING DIRECTIVES: #ifdef
, #if defined()
, …
In this case there are specific MACROS for each operating system, for example:
__linux__
;_WIN32
.Below is an example of C++ code that runs on both operating systems and emits a “Hello, World!” depending on the operating system:
#include <iostream>
int main(){
#if defined(__linux__) // Or #if __linux__
std::cout << "Hello, GNU/Linux!" << '\n';
#elif _WIN32
std::cout << "Hello, Windows!" << '\n';
#else
std::cout << "Hello, Other!" << '\n';
#endif
}
In case of Windows, you can still create another #if
inside to detect if:
_WIN64
, this Windows is 64-bit only;_WIN32
, both 64-bit and 32-bit__CYGWIN__
another more modern alternative.Example:
#include <iostream>
int main(){
#if __linux__
std::cout << "Hello, GNU/Linux!" << '\n';
#elif _WIN32
#if defined(_WIN64)
std::cout << "Hello, Windows 64-bit!" << '\n';
#else
std::cout << "Hello, Windows!" << '\n';
#endif
#else
std::cout << "Hello, Other!" << '\n';
#endif
}
You can still detect all operating systems. Below is another example that not only detects Linux and Windows, but also checks if it is: macOS, FreeBSD, Android:
#include <iostream>
int main(){
#if defined(__linux__) // Or #if __linux__
std::cout << "Hello, GNU/Linux!" << '\n';
#elif __FreeBSD__
std::cout << "Hello, FreeBSD!" << '\n';
#elif __ANDROID__
std::cout << "Hello, Android!" << '\n';
#elif __APPLE__
std::cout << "Hello, macOS!" << '\n';
#elif _WIN32
std::cout << "Hello, Windows!" << '\n';
#else
std::cout << "Hello, Other!" << '\n';
#endif
}
You can still check if it is UNIX type (Linux or BSD, macOS NOT): unix
, __unix
or __unix__
.
For a complete list of all macros for operating systems you can see here.
To have a list of macros you can detect, use gcc
or g++
:
It may be that
clang
andclang++
also have these options, but I haven’t reinstalled them for testing yet.
g++ -dM -E - </dev/null
# Or
gcc -dM -E - </dev/null
g++ -dM -E - <NUL:
# Or
gcc -dM -E - <NUL:
The output will be extensive:
Small snippet below.
#define __SSP_STRONG__ 3
#define __DBL_MIN_EXP__ (-1021)
#define __UINT_LEAST16_MAX__ 0xffff
#define __FLT16_HAS_QUIET_NAN__ 1
#define __ATOMIC_ACQUIRE 2
#define __FLT128_MAX_10_EXP__ 4932
#define __FLT_MIN__ 1.17549435082228750796873653722224568e-38F
#define __GCC_IEC_559_COMPLEX 2
#define __UINT_LEAST8_TYPE__ unsigned char
#define __SIZEOF_FLOAT80__ 16
#define __INTMAX_C(c) c ## L
#define __CHAR_BIT__ 8
#define __UINT8_MAX__ 0xff
#define __SCHAR_WIDTH__ 8
#define __WINT_MAX__ 0xffffffffU
#define __FLT32_MIN_EXP__ (-125)
#define __ORDER_LITTLE_ENDIAN__ 1234
#define __SIZE_MAX__ 0xffffffffffffffffUL
#define __WCHAR_MAX__ 0x7fffffff
#define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 1
...