我在一次采访中被问到如何仅通过提供可运行的 C 代码来识别平台?
代码必须在两个平台上都可以运行(即没有用于检查的特殊头文件功能)?
快速的谷歌搜索显示了这一点
#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 构造。本文调查了常见的编译器,并展示了如何使用预定义的宏在编译时检测常见的操作系统。
这个问题很奇怪。您不能提供可以在多个平台上运行的可执行文件。所以显而易见的答案是:在一个平台上编译它:如果它运行,那就是你所在的平台;如果不是,您在其他平台上。
假设您确实有单独的可执行文件,那么实际上没有真正的答案。首先,您认为“不同的平台”是什么?Sparc 上的 Linux 和 PC 上的 Linux 是不同的平台吗?那么两个不同版本的 Linux 呢?在 CygWin 下运行呢?但是,无论您如何定义它,您都可能需要对每个平台进行单独的测试。但是这个问题很愚蠢,因为除了考虑不同平台的不同版本之外,您需要为每个平台提供不同的可执行文件,这意味着无论如何您必须在编译时进行区分
仅作记录:对于初学者,我会使用 boost::filesystem,并尝试读取目录"c:\\"
和"/usr"
. 理论上,您可以"c:\\"
在 Unix 下拥有一个以当前目录命名的目录,或者"/usr"
在 Windows 下拥有一个以 C: 命名的目录,但绝对不可能。否则,请尝试. 该目录在 Windows 下几乎肯定不存在,即使存在,也不会有它在各种 Unix 下的动态结构。并且结构从一个Unix到另一个不同,所以你甚至应该能够区分Solaris和Linux。"/proc/myPID"
如果只是在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
,请参见此处。
大多数常用方法在编译时进行确定。
如果您真的坚持在运行时做出决定,您可以尝试使用一个设备(出于一种可能性)存在于一个设备上但不存在于另一个设备上(例如,尝试打开一个名为的文件/dev/null
应该可以在 Linux 上工作,但在 Windows 上通常会失败)。
如果您只考虑 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
每个平台都定义了自己的预处理器指令。您必须在其中编写代码。
如何使用预处理器指令检查操作系统? 请按照上面的链接。可能是重复的问题。