我需要我的代码根据编译它的操作系统来做不同的事情。我正在寻找这样的东西:
#ifdef OSisWindows
// do Windows-specific stuff
#else
// do Unix-specific stuff
#endif
有没有办法做到这一点?有没有更好的方法来做同样的事情?
C
而不是 C++
Predefined Macros for OS 网站有一个非常完整的检查列表。以下是其中一些,并带有指向它们所在位置的链接:
视窗
_WIN32
32 位和 64 位
_WIN64
64 位
__CYGWIN__
Unix(Linux、*BSD,但不是 Mac OS X)
请参阅此related question,了解使用此检查的一些缺陷。
unix
__unix
__unix__
Mac OS X
__APPLE__
也用于经典
__MACH__
两者都被定义;检查任何一个都应该工作。
Linux
__linux__
linux
已过时(不符合 POSIX)
__linux
已过时(不符合 POSIX)
自由BSD
__FreeBSD__
安卓
__ANDROID__
在 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
unix
、__unix__
、__unix
在仅定义了 __APPLE__
和 __MACH__
的 macOS 上不起作用。
基于 nadeausoftware 和 Lambda 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
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)
在大多数情况下,最好检查给定的功能是否存在。例如:函数pipe()
是否存在。
#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
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__
为您预定义的适当编译器做一个谷歌。
在 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/
没有根据 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
您可以使用 Boost.Predef
,其中包含用于目标平台的各种预定义宏,包括操作系统 (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
operating system macros 中找到
另请参阅How to get platform ids from boost
很抱歉外部参考,但我认为它适合您的问题:
C/C++ tip: How to detect the operating system type using compiler predefined macros
使用 #define OSsymbol
和 #ifdef OSsymbol
,其中 OSsymbol 是用于标识您的目标操作系统的 #define
符号。
通常,您将包含一个定义所选 OS 符号的中央头文件,并使用特定于 OS 的包含和库目录来编译和构建。
您没有指定您的开发环境,但我很确定您的编译器为通用平台和操作系统提供了全局定义。
另请参阅http://en.wikibooks.org/wiki/C_Programming/Preprocessor
总结一下,这里有一堆有用的链接。
GCC 通用预定义宏
SourceForge 预定义的操作系统
MSDN 预定义宏
链接多的 NaudeaSoftware 页面
维基百科!!!
SourceForge 的“标准、编译器、操作系统和硬件架构的预定义编译器宏概述”。
FreeBSD 的“差异化操作系统”
各种预定义宏
可移植的
您可以在编译时使用预处理器指令作为警告或错误来检查您根本不需要运行这个程序,只需简单地编译它。
#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;
}
我编写了一个 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。
__unix__
。你为什么要把它列入清单?unix
符号而不定义win32
符号,所以要小心。 OTOH 它确实定义了__CYGWIN__
。__linux__
与__ANDROID__
相同吗?