【问题标题】:Identify the platform linux or windows using C/C++ code [duplicate]使用 C/C++ 代码识别平台 linux 或 windows [重复]
【发布时间】:2013-07-02 02:18:52
【问题描述】:

我在一次采访中被问到如何仅通过提供可运行的 C 代码来识别平台?

代码必须在两个平台都可以运行(即没有用于检查的特殊头文件功能)?

【问题讨论】:

  • 这些问题是关于宏的,但我认为 OP 真的是在问你如何使用可以在多个平台上编译的代码来做到这一点。我建议探测文件系统中是否存在显示操作系统的文件。
  • 从概念上讲,在构建环境级别而不是语言级别解决这个问题可能更有意义。 IE。让构建环境定义一个预处理器标志,允许代码确定平台。否则,您将有关编译器的知识引入源代码中,这会限制可移植性并且总体上不是很好。
  • 我想问题不在于编译器指令,因为它们不是可运行的 c 代码,对吧?它更像是我使用什么代码来检测平台。很奇怪,因为无论如何您都必须为特定平台编译 C 代码。猜猜这个问题对我来说有点模棱两可。
  • 如何将其标记为重复。这是一个完全不同的问题。 (这可能是一个无意义的问题,或者一个没有答案的问题,但它肯定与作为重复链接的问题不同。)

标签: c++ c linux windows


【解决方案1】:

快速谷歌搜索显示此

#if defined(_WIN64)
    /* Microsoft Windows (64-bit). ------------------------------ */

#elif defined(_WIN32)
    /* Microsoft Windows (32-bit). ------------------------------ */

#endif

所有 C/C++ 编译器都预定义了操作系统标识宏,以启用 #if/#endif 集来包装特定于操作系统的代码。这在必须使用低级库函数进行快速磁盘 I/O、进程间通信或线程的跨平台代码中通常是必需的。虽然 Windows 和其他操作系统之间的差异很明显,但即使是 UNIX 风格的操作系统之间的差异也可能需要 #if/#endif 构造。本文调查了常见的编译器,并展示了如何在编译时使用预定义的宏来检测常见的操作系统。

http://nadeausoftware.com/articles/2012/01/c_c_tip_how_use_compiler_predefined_macros_detect_operating_system

【解决方案2】:

这个问题很奇怪。你不能提供一个可执行文件 可以在多个平台上运行。所以显而易见的答案是: 在一个平台上编译它:如果它运行,那就是平台 轮到你了;如果不是,您在其他平台上。

假设您确实有单独的可执行文件,确实有 没有真正的答案。首先,您认为“不同 平台”? Sparc 上的 Linux 和 PC 上的 Linux 不同吗? 平台?那么两个不同版本的 Linux 呢?什么 关于在 CygWin 下运行?不管你怎么定义, 但是,您可能需要对每个平台进行单独的测试。 但这个问题很愚蠢,因为,除了考虑 不同版本不同平台,你需要一个不同的 每个平台的可执行文件,这意味着您必须 无论如何在编译时区分

仅作记录:对于初学者,我会使用 boost::filesystem, 并尝试读取目录"c:\\""/usr"。理论上, 您可以在当前目录中有一个名为 "c:\\" 的目录 Unix 下的目录,或 C: 下名为 "/usr" 的目录 Windows,但可能性肯定是反对的。否则,请尝试 "/proc/<i>myPID</i>" 中的各种文件。这 目录在 Windows 下几乎肯定不存在,并且 即使有,它也不会有它所拥有的动态结构 各种Unix下。并且结构从一个 Unix 到 下一个,所以你甚至应该能够区分 Solaris 和 Linux。

如果只是在 PC 上的 Windows 和 Linux 之间进行比较,则 当然,最简单的就是在32位模式下编译,取 局部变量的地址。如果大于 0x8000000, 你在Linux下;如果它更少,Windows。

【讨论】:

  • 如果我们只能在两个平台上以 64 位模式编译,有没有办法区分两个平台的地址?
【解决方案3】:

这有点模糊。除非您在 Wine 下运行,否则二进制文件不会在两个系统中运行(请参阅 http://wiki.winehq.org/DeveloperFaq#detect-wine )。

在编译时,您可以检查特定于 Windows 或 Linux 的 #defines,但可以说这是特定于编译器和支持的标准,所以我不确定您是否“允许”这样做面试问题(可以说是因为你的“没有用于检查的特殊头文件功能”的限制)。

一般来说,我认为优先于编译时检查没有任何意义,而且它在 Wine 下可能不起作用,但您可以使用 dlsym() 来检查自己是否存在已知的符号操作系统之一,或查看您自己的可执行映像以了解它是什么。

实际上,您也很有可能检查您的环境变量并据此做出相当好的判断,尽管有人可能会故意欺骗您的程序进行不正确的评估,或者您的判断方法可能会在未来版本的操作系统,在不同的外壳等下......

在运行时,您可以例如stat("/dev", &amp;buf),它应该只适用于 Linux。尝试popen(3) 说uname 是另一种可行的方法:如果您在Linux 上,您将能够阅读“linux\n”,而类似cygwin 的环境apparently reports NTsee here too

【讨论】:

  • 您提到 Wine 是一个有趣的问题。在 Wine 下运行的程序应该报告 Windows 还是 Linux? (对于在 Windows 下使用 CygWin 库编译的程序也是如此。)
  • 与 Cygwin 的相反是不可能的。它是一个源兼容层(不是二进制),因此必须专门为它编译代码。它不在 Windows 上运行 Linux 二进制文件(Wine 在 Linux 上运行 Windows 二进制文件的方式)。
【解决方案4】:

大多数常用方法在编译时进行判断。

如果您真的坚持在运行时做出决定,您可以尝试使用一个设备(出于一种可能性),该设备存在于一个设备上但不存在于另一个设备上(例如,尝试打开一个名为 /dev/null 的文件应该可以Linux 但在 Windows 上通常会失败)。

【讨论】:

  • 杰瑞,如果存在目录 C:\dev 和文件 C:\dev\null 怎么办?例如,此命令在这种情况下可以正常工作:notepad /dev/null.
  • @skwllsp:是的——这就是我说“通常”的原因。如果您需要更确定的可能性,我想您可以创建一个目录,然后立即查看是否可以在该目录中打开一个名为“NUL”的文件(将在 Windows 上工作,而不是在 Linux 上工作)。
  • @JerryCoffin 如果唯一的可能性是 PC 上的 Windows 和 Linux,那么最简单的(至少在 32 位模式下)就是在 main 中获取局部变量的地址。如果它小于0x80000000,则说明您在 Windows 下。如果它更大,Linux。
  • @JamesKanze:对我来说这听起来是一个很好的答案。
  • @JerryCoffin 这对我来说听起来像是一个很大的如果。使用此规则,Sparc 上的 Solaris 将看起来像 Linux; HP-UX 将像 Windows 一样显示。而且我不知道苹果会出现什么。 (可能是 Linux,因为它是使用 g++ 并在 Intel 架构上运行的 Unix。但你永远不知道。)
【解决方案5】:

除了通常的 MACRO 调用:

#ifdef _WIN32
  ...

#if defined (_MSC_VER)
  ...

#ifdef __unix__
  ...

您可以简单地使用getenv() 函数并测试some variables set,例如SHELLWINDIR。需要决定的有趣案例:

  • windows 32/64下的mingw 32/64
  • windows 32/64下的cygwin 32/64
  • linux下的wine 32/64

当然,“Windows”环境变量也可以在 Linux 中设置 - 反之亦然。

【讨论】:

    【解决方案6】:

    如果您只考虑 Linux 平台或 Windows 平台,则此代码将根据您的需要在 C 和 C++ 上运行。

    #include <stdio.h>
    
    #if defined(__linux__) // any linux distribution
        #define PLATFORM "linux"
    #elif defined(_WIN32) // any windows system
        #define PLATFORM "windows"
    #else
        #define PLATFORM "Is not linux or windows"
    #endif
    
    
    int main(int argc, char *argv[]) {
        puts(PLATFORM);
        return 0;
    }
    

    带有示例的完整答案见https://stackoverflow.com/a/42040445/6003870

    【讨论】:

      【解决方案7】:

      每个平台都定义了自己的预处理器指令。您必须在其中编写代码。

      How do I check OS with a preprocessor directive? 请按照上面的链接。可能是重复的问题。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-01-29
        • 1970-01-01
        • 1970-01-01
        • 2023-04-06
        • 2010-09-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多