257

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

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

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

4

16 回答 16

385

操作系统的预定义宏站点有一个非常完整的检查列表。以下是其中一些,并带有指向它们所在位置的链接:

视窗

_WIN32   32 位和 64
_WIN64   位 仅 64 位
__CYGWIN__

Unix(Linux、*BSD,但不是 Mac OS X)

有关使用此检查的一些陷阱,请参阅此相关问题

unix
__unix
__unix__

Mac OS X

__APPLE__也用于经典
__MACH__

两者都被定义;检查任何一个都应该工作。

Linux

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

自由BSD

__FreeBSD__

安卓

__ANDROID__

于 2011-11-23T21:21:42.100 回答
79

在 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
于 2009-03-15T11:12:04.427 回答
53

基于nadeausoftwareLambda Fairy 的回答

#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
const 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
  • 视窗 (MinGW)
  • 窗口(Cygwin)
于 2017-02-04T12:37:07.633 回答
8

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

于 2008-09-26T23:55:01.310 回答
8

Microsoft C/C++ 编译器 (MSVC) 预定义宏可在此处找到

我认为您正在寻找:

  • _WIN32- 当编译目标是 32 位 ARM、64 位 ARM、x86 或 x64 时定义为 1。否则,未定义
  • _WIN64- 当编译目标是 64 位 ARM 或 x64 时定义为 1。否则,未定义。

gcc 编译器 PreDefined MAcros 可以在这里找到

我认为您正在寻找:

  • __GNUC__
  • __GNUC_MINOR__
  • __GNUC_PATCHLEVEL__

为您预定义的适当编译器做一个谷歌。

于 2008-09-26T23:58:19.163 回答
8
#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
于 2014-02-21T16:41:27.697 回答
5

在 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/

于 2017-01-27T14:49:04.870 回答
4

没有根据 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
于 2008-09-27T00:08:43.273 回答
3

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

C/C++ 技巧:如何使用编译器预定义的宏来检测操作系统类型

于 2015-07-30T21:15:55.043 回答
3

您可以使用Boost.Predef其中包含目标平台的各种预定义宏,包括 OS ( BOOST_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)
#elif defined(BOOST_OS_AIX)
#elif defined(BOOST_OS_HAIKU)
...
#endif

完整列表可在BOOST_OS操作系统宏中找到

另请参阅如何从 boost 中获取平台 ID

于 2018-10-25T14:54:36.820 回答
2

使用#define OSsymbol#ifdef OSsymbol 其中 OSsymbol 是#define标识目标操作系统的“功能符号”。

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

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

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

于 2008-09-26T23:52:50.240 回答
1

我在这里没有找到俳句定义。完整地说,Haiku-os 的定义很简单__HAIKU__

于 2018-10-11T20:05:57.327 回答
0

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

于 2008-09-26T23:52:06.607 回答
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;
}
于 2018-01-10T21:44:44.070 回答
0

我编写了一个小库来获取您所在的操作系统,它可以使用clib(C 包管理器)安装,因此将它用作项目的依赖项非常简单。

安装

$ clib install abranhe/os.c

用法

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

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

它返回一个字符串 ( char*),其中包含您正在使用的操作系统的名称,有关此项目的更多信息,请查看Github 上的文档

于 2018-11-12T17:33:12.947 回答