哪个跨平台预处理器定义? (__WIN32__ 或 __WIN32 或 WIN32 )?
Posted
技术标签:
【中文标题】哪个跨平台预处理器定义? (__WIN32__ 或 __WIN32 或 WIN32 )?【英文标题】:Which Cross Platform Preprocessor Defines? (__WIN32__ or __WIN32 or WIN32 )? 【发布时间】:2011-02-28 17:00:39 【问题描述】:我经常看到__WIN32
、WIN32
或__WIN32__
。我认为这取决于使用的预处理器(来自 Visual Studio 或 gcc 等)。
我现在必须先检查 os,然后再检查使用的编译器吗?我们在这里使用 G++ 4.4.x、Visual Studio 2008 和 Xcode(我假设又是一个 gcc)和 ATM,我们只使用 __WIN32__
、__APPLE__
和 __LINUX__
。
【问题讨论】:
_WIN32
是系统性的,比其他拼写更冒犯。见sourceforge.net/p/predef/wiki/OperatingSystems。好的做法是测试每种情况(操作系统、架构、编译器......)的相关内容,而不是针对另一种情况进行测试。也不要重新定义你自己的。
【参考方案1】:
不明白为什么必须这样做。您可能必须记住在编译器的命令行上手动指定定义,但仅此而已。作为记录,Visual Studio 的定义是_WIN32
(带一个下划线)而不是__WIN32
。如果没有定义就没有定义,也没关系。
【讨论】:
所以我只能写一次#ifdef __WIN32__
而不是#ifdef WIN32 || __WIN32 || __WIN32__
@brubelsabs:是的,但如果您决定使用其他编译器,则必须记住自己在命令行中输入预处理器定义。
AFAIK _WIN32
是为所有(现代)Windows 编译器(当然不包括 WinCE)定义的。无需自己定义...
@math:你的#ifdef
-表达式是错误的。应该是#if defined(WIN32) || defined(__WIN32) || defined(__WIN32__)
。参考C Preprocessor directives and boolean operators。
@IInspectable:或者#if WIN32 || _WIN32 || __WIN32__
。未定义的名称被视为零。问题是在#define _WIN32 0
的情况下应该怎么做。【参考方案2】:
我已经重建了我的答案...该死的,正在疯狂编辑:P:
您不需要使用部分的。对于 MacOSX、Linux 和其他类 Unix 系统,您可能根本不需要使用任何工具。
最受欢迎的是(据 Google 所说)是_WIN32
。
您从不在源代码中“手动”定义它。它以下列方式之一定义:
作为命令行预处理器/编译器标志(如g++ -D _WIN32
)
或者它是由编译器本身预定义的(大多数 Windows 编译器都预定义了_WIN32
,有时也预定义了WIN32
或_WIN32_
。--那么你根本不需要担心定义它,编译器会完成整个工作。
我的旧答案:
您不必“必须”做任何事情。它只是为了多平台兼容性。通常所有类 Unix(包括 Linux、MacOSX、BSD、Solaris...)和其他 POSIX 平台的代码版本将完全相同,并且必须对 Windows 进行一些更改。所以人们通常为类 Unix 编写他们的代码,并在#ifdef _WIN32
和#endif
之间放置一些仅限 Windows(例如 DirectX 指令、类 Windows 文件路径...)的部分。
如果您有一些零件,例如。仅 X-Window 系统或仅 MacOS,您可以使用 #ifdef X_WINDOW
或 #ifdef MACOS
之类的东西进行类似操作。然后,您需要在编译时设置适当的预处理器定义(使用 gcc 使用 -D 标志,例如 gcc -D _WIN32
)。
如果你不编写任何依赖于平台的代码,那么你就不需要关心这样的#ifdef, #else, #endif
块。大多数 Windows 编译器/预处理器 AFAIK 都预定义了一些符号,如 _WIN32
(最流行,据 google 说实话)、WIN32
、_WIN32_
等。所以在 Windows 上编译它很可能你不会除了编译之外,还需要做任何其他事情。
【讨论】:
可能我的问题很不清楚:我不想定义 WIN32,而是将它与#ifdef
一起使用。我想知道为什么有这么多变体,是否有一个可以与大多数编译器一起使用。
正如我所说,人们只是使用他们喜欢的东西,没有标准。无论如何,您可以在命令行中(以及 IDE 选项等)编译自己时定义它,因此使用“不支持”的 WIN32__ 而不是“好”的 _WIN32 不是问题。而且,正如我所说,大多数编译器支持 _WIN32,有些支持许多其他编译器(mingw 支持 WIN32 _WIN32 WIN32 __WIN32 MINGW32 WINNT WINNT __WINNT)。看到这个:***.com/questions/142508/…【参考方案3】:
这取决于你想要做什么。如果您的程序想要使用某些特定功能(例如来自 gcc 工具链),您可以检查编译器。如果您想使用某些操作系统特定的功能(无论编译器如何 - 例如 Windows 上的 CreateProcess 和 unix 上的 fork),您可以检查操作系统( _WINDOWS、__unix__ )。
Macros for Visual C
Macros for gcc
您必须检查每个编译器的文档,以便能够在编译时检测到差异。我记得 gnu 工具链(gcc)在 C 库(@987654323@)中有一些其他工具链(例如 Visual C)中没有的函数。这样,如果您想在商品之外使用这些功能,那么您必须检测到您正在使用 GCC,因此您必须使用的代码如下:
#ifdef __GNUC__
// do my gcc specific stuff
#else
// ... handle this for other compilers
#endif
【讨论】:
【参考方案4】:叹气 - 不要依赖编译器 - 在 Makefile 中指定您正在构建的平台。简而言之,以 _ 开头的任何内容都依赖于实现而不是可移植的。
我曾经在一个非常大的项目中尝试过你的方法,在 Sun-C++ 和 GCC 之间来回切换,我们只是决定使用 Makefile 控制,而不是试图推断编译器将要做什么。
【讨论】:
您可以为不同的行为创建包装器并使用这些包装器。这样,您只需在几个源文件中处理平台/编译器差异,(在我看来)这比处理每个平台的 makefile 更好。 你有一个有效的点。但是,我无法想象您支持多个平台并且不使用某种 Makefile(gmake/cmake/qmake)的情况。 link.exe 的 Windows 库定义与 gcc -L -l 不同。编译器优化设置也不是。我宁愿在一个 Makefile(或几个包含)中处理我的平台标志,而不是必须记住在每个头文件/源文件中包含 platform_magic.h。 Boost 会按照你的方式去做——在 boost/system/config.hpp 中,它决定了它在哪个平台上运行。我们只需要同意不同意。 :-D【参考方案5】:这篇文章回答了你的问题:
C/C++ tip: How to detect the operating system type using compiler predefined macros(加上archive.org link,以防它消失)。这篇文章很长,并且包含难以复制的表格,但这里是精髓:
您可以通过以下方式检测 Unix 风格的操作系统:
#if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__)))
/* UNIX-style OS. ------------------------------------------- */
#endif
一旦你知道它是 Unix,你就可以找到它是否是 POSIX 和 POSIX 版本:
#include <unistd.h>
#if defined(_POSIX_VERSION)
/* POSIX compliant */
#endif
您可以通过以下方式检查 BSD 派生系统:
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
#include <sys/param.h>
#if defined(BSD)
/* BSD (DragonFly BSD, FreeBSD, OpenBSD, NetBSD). ----------- */
#endif
#endif
和 Linux:
#if defined(__linux__)
/* Linux */
#endif
和苹果的操作系统
#if defined(__APPLE__) && defined(__MACH__)
/* Apple OSX and ios (Darwin) */
#include <TargetConditionals.h>
#if TARGET_IPHONE_SIMULATOR == 1
/* iOS in Xcode simulator */
#elif TARGET_OS_IPHONE == 1
/* iOS on iPhone, iPad, etc. */
#elif TARGET_OS_MAC == 1
/* OS X */
#endif
#endif
带有 Cygwin 的 Windows
#if defined(__CYGWIN__) && !defined(_WIN32)
/* Cygwin POSIX under Microsoft Windows. */
#endif
非 POSIX Windows 具有:
#if defined(_WIN64)
/* Microsoft Windows (64-bit) */
#elif defined(_WIN32)
/* Microsoft Windows (32-bit) */
#endif
全文列出了以下符号,并显示了哪些系统定义了它们以及何时定义它们:_AIX
、__APPLE__
、__CYGWIN32__
、__CYGWIN__
、__DragonFly__
、__FreeBSD__
、__gnu_linux
、@987654339 @,__hpux
,linux
,__linux
,__linux__
,__MACH__
,__MINGW32__
,__MINGW64__
,__NetBSD__
,__OpenBSD__
,_POSIX_IPV6
,_POSIX_IPV6
,_POSIX_IPV6
,@9876 _POSIX_THREADS
,_POSIX_VERSION
,sun
,__sun
,__SunOS
,__sun__
,__SVR4
,__svr4__
,TARGET_IPHONE_SIMULATOR
,TARGET_OS_EMBEDDED
,TARGET_OS_IPHONE
,TARGET_OS_MAC
,UNIX
,unix
,__unix
,__unix__
,WIN32
,_WIN32
,__WIN32
,__WIN32__
,WIN64
,_WIN64
,@987654375,@,@987654375,@,@987654376 __WINNT
, __WINNT__
.
A related article (archive.org link) 涵盖了检测编译器和编译器版本。它列出了以下符号:__clang__
、__GNUC__
、__GNUG__
、__HP_aCC
、__HP_cc
、__IBMCPP__
、__IBMC__
、__ICC
、__INTEL_COMPILER
、_MSC_VER
3、 __SUNPRO_C
,__SUNPRO_CC
用于检测编译器,__clang_major__
,__clang_minor__
,__clang_patchlevel__
,__clang_version__
,__GNUC_MINOR__
,__GNUC_PATCHLEVEL__
,__GNUC__
,@9876544399@9876544399@9801 @, __IBMCPP__
, __IBMC__
, __ICC
, __INTEL_COMPILER
, __INTEL_COMPILER_BUILD_DATE
, _MSC_BUILD
, _MSC_FULL_VER
, _MSC_VER
, __PGIC_MINOR__
, @987644412@, __PGIC__
, __PGIC__
, _MSC_FULL_VER
__SUNPRO_CC
、__VERSION__
、__xlC_ver__
、__xlC__
、__xlc__
用于检测编译器版本。
【讨论】:
链接可能会损坏,我只是在没有任何解释的情况下发布链接,我认为这不是一种好的 QA 风格。即使这只是一个评论。请尝试总结文章。 好电话。我更新了这篇文章以提供更多详细信息,还提供了指向 archive.org 的链接以更好地处理网站消失问题。以上是关于哪个跨平台预处理器定义? (__WIN32__ 或 __WIN32 或 WIN32 )?的主要内容,如果未能解决你的问题,请参考以下文章