如何使用预处理程序指令检查OS?

时间:2008-09-26 23:44:00

标签: c operating-system c-preprocessor conditional-compilation

我需要我的代码根据编译它的操作系统做不同的事情。我正在寻找这样的东西:

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

有办法做到这一点吗?是否有更好的方法来做同样的事情?

16 个答案:

答案 0 :(得分:228)

Predefined Macros for OS 网站有一个非常完整的检查列表。以下是其中的一些内容,以及指向它们的位置的链接:

Windows

_WIN32 32位和64位
_WIN64仅限64位

Unix(Linux,* BSD,Mac OS X)

有关使用此项检查的一些缺陷,请参阅此related question

unix
__unix
__unix__

Mac OS X

__APPLE__
__MACH__

两者都是定义的;检查要么应该工作。

Linux

__linux__
linux已过时(不符合POSIX)
__linux已过时(不符合POSIX)

FreeBSD

__FreeBSD__

答案 1 :(得分:63)

在Windows上显示GCC定义:

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

答案 2 :(得分:20)

基于nadeausoftwareLambda Fairy's answer

#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)

答案 3 :(得分:10)

在大多数情况下,最好检查是否存在给定的功能。例如:如果函数pipe()存在或不存在。

答案 4 :(得分:7)

#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 :(得分:5)

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__

为您预先定义的相应编译器做谷歌。

答案 6 :(得分:3)

没有根据C标准设置的标准宏。有些C编译器会在某些平台上设置一个(例如Apple的补丁GCC设置一个宏来表示它正在Apple系统和Darwin平台上进行编译)。您的平台和/或C编译器也可以设置一些东西,但没有通用的方法。

就像hayalci所说的那样,最好在构建过程中以某种方式设置这些宏。在不修改代码的情况下,很容易用大多数编译器定义宏。您可以简单地将-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

答案 7 :(得分:3)

在MinGW上,#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 定义检查不起作用。这是一个解决方案:

{{1}}

有关详细信息,请查看:https://sourceforge.net/p/predef/wiki/OperatingSystems/

答案 8 :(得分:2)

使用#define OSsymbol#ifdef OSsymbol 其中OSsymbol是一个#define'符号,用于标识您的目标操作系统。

通常,您将包含一个定义所选OS符号的中央头文件,并使用特定于操作系统的include和库目录进行编译和构建。

您没有指定开发环境,但我非常确定您的编译器为常见平台和操作系统提供了全局定义。

另见http://en.wikibooks.org/wiki/C_Programming/Preprocessor

答案 9 :(得分:2)

很抱歉外部参考,但我认为它适合您的问题:

C/C++ tip: How to detect the operating system type using compiler predefined macros

答案 10 :(得分:2)

答案 11 :(得分:1)

有些编译器会生成#defines来帮助你解决这个问题。阅读编译器文档以确定它们是什么。 MSVC定义了一个__WIN32__GCC有一些touch foo.h; gcc -dM foo.h

答案 12 :(得分:0)

您可以使用预处理器指令作为 警告或错误 在编译时检查您是否需要运行这个程序根本就是编译它。

#if defined(_WIN32) || defined(_WIN64) || defined(__WINDOWS__)
    #error Windows_OS
#elif defined(__linux__)
    #error Linux_OS
#elif defined(__APPLE__) && defined(__MACH__)
    #error Mach_OS
#elif defined(unix) || defined(__unix__) || defined(__unix)
    #error Unix_OS
#else
    #error Unknown_OS
#endif

#include <stdio.h>
int main(void)
{
    return 0;
}

答案 13 :(得分:0)

我在这里找不到Haiku的定义。为了完整起见,Haiku-os的定义很简单__HAIKU__

答案 14 :(得分:0)

您可以使用Boost.Predef,其中包含用于目标平台(包括OS)的各种预定义宏。是的,boost通常被认为是C ++库,但这是一个预处理器标头,也可以与C一起使用

  

此库从其可以收集的C,C ++,Objective C和Objective C ++预定义宏或通常可用的头文件中定义的信息中定义了一组编译器,体系结构,操作系统,库和其他版本号。该库的想法源自提议扩展Boost Config库,以提供比其支持的功能定义更多,更一致的信息。接下来是该简短建议的编辑版本。

例如

#include <boost/predef.h>

#if defined(BOOST_OS_WINDOWS)
#elif defined(BOOST_OS_ANDROID)
#elif defined(BOOST_OS_LINUX)
#elif defined(BOOST_OS_BSD)
...
#endif

答案 15 :(得分:0)

我写了一个small library以获取您所使用的操作系统,可以使用clib(C程序包管理器)进行安装,因此使用它作为您的依赖项真的很简单项目。

安装

$ clib install abranhe/os.c

用法

#include <stdio.h>
#include "os.h"

int main()
{
    printf("%s\n", operating_system());
    // macOS
    return 0;
}

它返回带有您使用的操作系统名称的字符串(char*),有关此项目的更多信息,请查看the documentation on Github