使用C / C ++代码识别平台linux或windows

Identify the platform linux or windows using C/C++ code

本问题已经有最佳答案,请猛点这里访问。

我在接受采访时被问到,如何通过提供可运行的C代码来识别平台?

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


快速谷歌搜索显示这一点

1
2
3
4
5
6
7
#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结构。本文调查了常见的编译器,并展示了如何在编译时使用预定义的宏来检测常见的OS。

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


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

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

仅供记录:对于初学者,我使用boost :: filesystem,
并尝试读取目录"c:\\""/usr"。理论上,
你可以在当前有一个名为"c:\\"的目录
Unix下的目录,或者C:下的名为"/usr"的目录
Windows,但可能性肯定是反对它。否则,试试
"/proc/myPID"中的各种文件。该
Windows下几乎肯定不存在目录,并且
即使它确实如此,它也不具备动态结构
在各种Unix下。结构因Unix而异
接下来,所以你甚至应该能够区分
Solaris和Linux。

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


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

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

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

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

在运行时,您可以例如stat("/dev", &buf),它只适用于Linux。尝试popen(3)说uname是另一种看似合理的方法:如果你在Linux上,你将能够阅读"linux n",而类似cygwin的环境显然报告NT,请参阅此处太。


除了通常的MACRO调用:

1
2
3
4
5
6
7
8
#ifdef _WIN32
  ...

#if defined (_MSC_VER)
  ...

#ifdef __unix__
  ...

您可以简单地使用getenv()函数并测试一些设置为SHELLWINDIR的变量。有趣的案例决定:

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

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


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

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


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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#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


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

如何使用预处理程序指令检查OS?
请点击以上链接。这可能是重复的问题。