ChatGPT解决这个技术问题 Extra ChatGPT

如何使用预处理器指令检查操作系统?

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

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

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

@Cory Klein:不,不。这个问题早在几年前就被问过了
这是关于 C 而不是 C++
@CoryKlein 不,该问题与此问题重复。
@AkibAzmain 你把我拉回了历史!哇,多么古老的问题。 7年前我第一次发表评论时已经5岁了!有趣的是,比较年龄并不是选择哪个是重复的明确标准,但在这种情况下,看起来另一个在年龄之前被标记为重复,所以这是一个没有实际意义的问题。祝你有美好的一天!

S
Steve Summit

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__


给出的这个站点不包括 iOS,因此无法区分 iOS 和 OS X。
Mac OS 没有定义 __unix__。你为什么要把它列入清单?
cpp -dM /dev/null 将为您提供已安装 gcc 版本上所有 gcc 预定义宏的列表
Cygwin 定义了 unix 符号而不定义 win32 符号,所以要小心。 OTOH 它确实定义了 __CYGWIN__
__linux____ANDROID__ 相同吗?
M
MD XF

在 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

Windows 和 Unices 不是唯一的操作系统
这很方便,但请注意 unix__unix____unix 在仅定义了 __APPLE____MACH__ 的 macOS 上不起作用。
S
Simon Kissane

基于 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
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)


亲爱的@MD XF,请注明您的 Windows、MinGW 和 Cygwin 版本
Windows 7 企业版 6.1.7601。赛格温 2.7.0-1。我找不到 MinGW 版本,但我昨天下载了它。
不过,您可能应该知道 - 该程序是标准 C,因此它应该适用于所有兼容的系统。
亲爱的@MD XF,感谢您提供此信息。我在这个答案的顶部添加了你作为贡献者。
M
MD XF

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


有没有一种简单的方法来检查是否定义了函数?
如果您使用自动配置,您可以使用 AC_CHECK_FUNCS() 检查函数。如果函数可用,AC_CHECK_FUNCS(pipe sqrt) 将定义 HAVE_PIPE 和 HAVE_SQRT。我不知道其他构建工具的情况如何,但我想他们在某种程度上也支持这一点。
@MDXF 从 C++17 开始,有 __has_include。我认为它还没有在 C 中标准化,但是所有主要的编译器(GCC、Clang、ICC、MSVC)都将它作为特定于供应商的扩展来实现,即使在 C 模式下也是如此。
M
MD XF
#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

C
Community

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__

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


a
anakod

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


最佳答案,因为它涵盖了 cygwin。
M
Mecki

没有根据 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

p
phuclv

您可以使用 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


S
Simon Kissane

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

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


该元帖子已被删除。有趣的是,一个询问因审核原因而被删除的帖子的元帖子因审核原因而被删除。
:) 是的。绝对疯狂
M
MD XF

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

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

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

另请参阅http://en.wikibooks.org/wiki/C_Programming/Preprocessor


M
MD XF

总结一下,这里有一堆有用的链接。

GCC 通用预定义宏

SourceForge 预定义的操作系统

MSDN 预定义宏

链接多的 NaudeaSoftware 页面

维基百科!!!

SourceForge 的“标准、编译器、操作系统和硬件架构的预定义编译器宏概述”。

FreeBSD 的“差异化操作系统”

各种预定义宏

可移植的


T
TadejP

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


M
MD XF

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


gcc:错误:无法识别的命令行选项'--show-defines' gcc:致命错误:没有输入文件编译终止。
H
Haseeb Mir

您可以在编译时使用预处理器指令作为警告或错误来检查您根本不需要运行这个程序,只需简单地编译它。

#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;
}

a
abrahamcalf

我编写了一个 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