如何在 C 预处理器中可靠地检测 Mac OS X、iOS、Linux、Windows? [复制]
Posted
技术标签:
【中文标题】如何在 C 预处理器中可靠地检测 Mac OS X、iOS、Linux、Windows? [复制]【英文标题】:How to detect reliably Mac OS X, iOS, Linux, Windows in C preprocessor? [duplicate] 【发布时间】:2011-08-20 16:06:27 【问题描述】:如果有一些跨平台的 C/C++ 代码应该在 Mac OS X、ios、Linux、Windows 上编译,我如何在预处理过程中可靠地检测到它们?
【问题讨论】:
【参考方案1】:大多数编译器都使用预定义的宏,您可以找到列表here。 GCC 编译器预定义的宏可以在here 找到。 这是 gcc 的一个示例:
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
//define something for Windows (32-bit and 64-bit, this part is common)
#ifdef _WIN64
//define something for Windows (64-bit only)
#else
//define something for Windows (32-bit only)
#endif
#elif __APPLE__
#include <TargetConditionals.h>
#if TARGET_IPHONE_SIMULATOR
// iOS, tvOS, or watchOS Simulator
#if TARGET_OS_MACCATALYST
// Mac's Catalyst (ports iOS API into Mac, like UIKit).
#elif TARGET_OS_IPHONE
// iOS, tvOS, or watchOS device
#elif TARGET_OS_MAC
// Other kinds of Apple platforms
#else
# error "Unknown Apple platform"
#endif
#elif __linux__
// linux
#elif __unix__ // all unices not caught above
// Unix
#elif defined(_POSIX_VERSION)
// POSIX
#else
# error "Unknown compiler"
#endif
定义的宏取决于您要使用的编译器。
_WIN64
#ifdef
可以嵌套到 _WIN32
#ifdef
中,因为在面向 Windows x64 版本时甚至定义了 _WIN32
。如果某些标头包含对两者都是通用的,这可以防止代码重复
(同样 WIN32
不带下划线允许 IDE 突出显示正确的代码分区)。
【讨论】:
@Paul, "代码应该在 Mac OS X、iOS、Linux、Windows 上编译" 还有更多...应该是#if TARGET_OS_IPHONE
而不是#ifdef
,因为TARGET_OS_IPHONE
在Mac 上被定义为0
。
根据 SourceForge 的说法,_WIN32 是为 32 位和 64 位版本的 Windows 定义的,所以不应该将 _WIN64 放在 _WIN32 之前吗?
@jdknight yes __linux__
是所有 linux 发行版都支持的宏,__linux
并非所有 linux 发行版都支持,__unix__
也应该用来代替 __unix
原因,因为所有遵循 unix 指南的平台都支持__unix__
,而不是__unix
,这里有更深入的描述nadeausoftware.com/articles/2012/01/…
另加__android__
【参考方案2】:
正如 Jake 指出的那样,TARGET_IPHONE_SIMULATOR
是 TARGET_OS_IPHONE
的子集。
另外,TARGET_OS_IPHONE
是TARGET_OS_MAC
的子集。
所以更好的方法可能是:
#ifdef _WIN64
//define something for Windows (64-bit)
#elif _WIN32
//define something for Windows (32-bit)
#elif __APPLE__
#include "TargetConditionals.h"
#if TARGET_OS_IPHONE && TARGET_OS_SIMULATOR
// define something for simulator
// (although, checking for TARGET_OS_IPHONE should not be required).
#elif TARGET_OS_IPHONE && TARGET_OS_MACCATALYST
// define something for Mac's Catalyst
#elif TARGET_OS_IPHONE
// define something for iphone
#else
#define TARGET_OS_OSX 1
// define something for OSX
#endif
#elif __linux
// linux
#elif __unix // all unices not caught above
// Unix
#elif __posix
// POSIX
#endif
注意上面检查TARGET_OS_SIMULATOR
宏,因为TARGET_IPHONE_SIMULATOR
宏自iOS 14以来已被弃用。
【讨论】:
我还要在__linux__
上方添加__ANDROID__
,因为它与Linux 相比有自己的特点。
这是否需要在 _WIN64
和 _WIN32
块中复制任何特定于 Windows 的代码(对于 32 位和 64 位都相同)?如果检测到_WIN64
,它将跳过_WIN32
,这可能是不可取的。像this 这样的东西可能会更好。
我的Linux只定义了__linux__
、__gnu_linux__
和linux
,但没有定义__linux
什么是#define TARGET_OS_OSX 1
? Apple 和 OS X 定义了自己的宏。【参考方案3】:
2021 年 1 月 5 日:感谢@Sadap 的评论,链接更新。
一种必然的回答:this site 上的人们已经花时间制作了为每个操作系统/编译器对定义的宏表。
例如,您可以看到 _WIN32
未在 Windows 上使用 Cygwin (POSIX) 定义,而它被定义为在 Windows、Cygwin(非 POSIX)和 MinGW 上使用所有可用编译器(Clang、GNU 、英特尔等)。
无论如何,我发现这些表格信息量很大,并想在这里分享。
【讨论】:
链接已失效。 @Lindydancer web.archive.org/web/20191012035921/http://nadeausoftware.com/…以上是关于如何在 C 预处理器中可靠地检测 Mac OS X、iOS、Linux、Windows? [复制]的主要内容,如果未能解决你的问题,请参考以下文章
如何通过 Mac OS X 上的 Unix 域套接字传递用户凭据?
如何检测 NaN 在哪里传递给 Mac OS X 10.9 上的 CoreGraphics API