Как проверить ОС с помощью директивы препроцессора? - PullRequest
158 голосов
/ 27 сентября 2008

Мне нужен мой код, чтобы делать разные вещи в зависимости от операционной системы, в которой он компилируется. Я ищу что-то вроде этого:

#ifdef OSisWindows
// do Windows-specific stuff
#else
// do Unix-specific stuff
#endif

Есть ли способ сделать это? Есть ли лучший способ сделать то же самое?

Ответы [ 16 ]

228 голосов
/ 24 ноября 2011

Предопределенные макросы для ОС имеют очень полный список проверок. Вот несколько из них со ссылками на то, где они находятся:

Windows

_WIN32 32-битная и 64-битная
_WIN64 Только 64 бит

Unix (Linux, * BSD, Mac OS X)

См. связанный вопрос о некоторых ловушках использования этой проверки.

unix
__unix
__unix__

Mac OS X

__APPLE__
__MACH__

Оба определены; проверка любого из них должна работать.

Linux

__linux__
linux Устаревший (не совместимый с POSIX)
__linux Устаревший (не POSIX-совместимый)

FreeBSD

__FreeBSD__

63 голосов
/ 15 марта 2009

show GCC определяет в Windows:

gcc -dM -E - <NUL:

в Linux:

gcc -dM -E - </dev/null

Предопределенные макросы в MinGW:

WIN32 _WIN32 __WIN32 __WIN32__ __MINGW32__ WINNT __WINNT __WINNT__ _X86_ i386 __i386

в UNIX:

unix __unix__ __unix
21 голосов
/ 04 февраля 2017

На основе nadeausoftware и Лямбда Фейри ответ .

#include <stdio.h>

/**
 * Determination a platform of an operation system
 * Fully supported supported only GNU GCC/G++, partially on Clang/LLVM
 */

#if defined(_WIN32)
    #define PLATFORM_NAME "windows" // Windows
#elif defined(_WIN64)
    #define PLATFORM_NAME "windows" // Windows
#elif defined(__CYGWIN__) && !defined(_WIN32)
    #define PLATFORM_NAME "windows" // Windows (Cygwin POSIX under Microsoft Window)
#elif defined(__ANDROID__)
    #define PLATFORM_NAME "android" // Android (implies Linux, so it must come first)
#elif defined(__linux__)
    #define PLATFORM_NAME "linux" // Debian, Ubuntu, Gentoo, Fedora, openSUSE, RedHat, Centos and other
#elif defined(__unix__) || defined(__APPLE__) && defined(__MACH__)
    #include <sys/param.h>
    #if defined(BSD)
        #define PLATFORM_NAME "bsd" // FreeBSD, NetBSD, OpenBSD, DragonFly BSD
    #endif
#elif defined(__hpux)
    #define PLATFORM_NAME "hp-ux" // HP-UX
#elif defined(_AIX)
    #define PLATFORM_NAME "aix" // IBM AIX
#elif defined(__APPLE__) && defined(__MACH__) // Apple OSX and iOS (Darwin)
    #include <TargetConditionals.h>
    #if TARGET_IPHONE_SIMULATOR == 1
        #define PLATFORM_NAME "ios" // Apple iOS
    #elif TARGET_OS_IPHONE == 1
        #define PLATFORM_NAME "ios" // Apple iOS
    #elif TARGET_OS_MAC == 1
        #define PLATFORM_NAME "osx" // Apple OSX
    #endif
#elif defined(__sun) && defined(__SVR4)
    #define PLATFORM_NAME "solaris" // Oracle Solaris, Open Indiana
#else
    #define PLATFORM_NAME NULL
#endif

// Return a name of platform, if determined, otherwise - an empty string
char *
get_platform_name() {
    return (PLATFORM_NAME == NULL) ? "" : PLATFORM_NAME;
}

int main(int argc, char *argv[]) {
    puts(get_platform_name());
    return 0;
}

Протестировано с GCC и лязгом:

  • Debian 8
  • Windows (MinGW)
  • Windows (Cygwin)
10 голосов
/ 27 сентября 2008

В большинстве случаев лучше проверить, присутствует ли данный функционал или нет. Например: если функция pipe() существует или нет.

7 голосов
/ 21 февраля 2014
#ifdef _WIN32
// do something for windows like include <windows.h>
#elif defined __unix__
// do something for unix like include <unistd.h>
#elif defined __APPLE__
// do something for mac
#endif
5 голосов
/ 27 сентября 2008

MS-компилятор Предопределенные макросы можно найти здесь:

http://msdn.microsoft.com/en-us/library/b0084kay(VS.80).aspx

Я думаю, что вы ищете:

_WIN32
_WIN64

Компилятор gcc PreDefined MAcros можно найти здесь:

http://gcc.gnu.org/onlinedocs/cpp/Predefined-Macros.html

Я думаю, что вы ищете:

__ GNUC __
__GNUC_MINOR __
__GNUC_PATCHLEVEL __

Сделайте гугл для ваших предопределенных компиляторов.

3 голосов
/ 27 января 2017

На MinGW проверка определения _WIN32 не работает. Вот решение:

#if defined(_WIN32) || defined(__CYGWIN__)
    // Windows (x86 or x64)
    // ...
#elif defined(__linux__)
    // Linux
    // ...
#elif defined(__APPLE__) && defined(__MACH__)
    // Mac OS
    // ...
#elif defined(unix) || defined(__unix__) || defined(__unix)
    // Unix like OS
    // ...
#else
    #error Unknown environment!
#endif

Для получения дополнительной информации смотрите: https://sourceforge.net/p/predef/wiki/OperatingSystems/

3 голосов
/ 27 сентября 2008

Нет стандартного макроса, который установлен в соответствии со стандартом C. Некоторые компиляторы C устанавливают один на некоторых платформах (например, исправленный GCC от Apple устанавливает макрос для указания того, что он компилируется в системе Apple и для платформы Darwin). Ваша платформа и / или ваш компилятор C могут также что-то установить, но общего способа нет.

Как сказал Хаялчи, лучше всего эти макросы установить в процессе сборки. С большинством компиляторов легко определить макрос без изменения кода. Вы можете просто передать -D MACRO в GCC, т.е.

gcc -D Windows
gcc -D UNIX

А в вашем коде:

#if defined(Windows)
// do some cool Windows stuff
#elif defined(UNIX)
// do some cool Unix stuff
#else
#    error Unsupported operating system
#endif
2 голосов
/ 31 июля 2015

Извините за внешнюю ссылку, но я думаю, что она подходит к вашему вопросу:

Совет C / C ++: как определить тип операционной системы с помощью предопределенных макросов компилятора

...