在 C,C + + 中检测 Windows 或 Linux

我正在写一个跨平台的程序。我希望这个程序可以在 Windows 和 Linux 下运行,所以我为这两个平台提供了两个不同的代码段。如果操作系统是 Windows,我希望运行第一段代码; 如果是 Linux,那么我希望运行第二段代码。

因此,我编写了以下代码,但是在 Windows 和 Linux 上构建时都出现了错误。我该怎么解决这个问题呢?

#ifdef __unix__                    /* __unix__ is usually defined by compilers targeting Unix systems */


#define OS_Windows 0
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>


#elif defined(_WIN32) || defined(WIN32)     /* _Win32 is usually defined by compilers targeting 32 or   64 bit Windows systems */


#define OS_Windows 1
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#define DIV 1048576
#define WIDTH 7


#endif


int main(int argc, char *argv[])
{
if(OS_Windows)
{
MEMORYSTATUSEX statex;
statex.dwLength = sizeof (statex);
GlobalMemoryStatusEx (&statex);


_tprintf (TEXT("There is  %*ld %% of memory in use.\n"),
WIDTH, statex.dwMemoryLoad);


}


else if(!OS_Windows) // if OS is unix


{
char cmd[30];
int flag = 0;
FILE *fp;
char line[130];
int memTotal, memFree, memUsed;


flag=0;
memcpy (cmd,"\0",30);
sprintf(cmd,"free -t -m|grep Total");
fp = popen(cmd, "r");
while ( fgets( line, sizeof line, fp))
{
flag++;
sscanf(line,"%*s %d %d %d",&TotalMem, &TotalUsed, &TotalFree);
}
pclose(fp);


if(flag)
printf("TotalMem:%d -- TotalUsed:%d -- TotalFree:%d\n",TotalMem,TotalUsed,TotalFree);
else
printf("not found\n");


}


return 0;
}
109702 次浏览

您应该在代码中使用相同的 #ifdef而不是 if(OS_Windows)逻辑:

#ifdef __unix__
...
#elif defined(_WIN32) || defined(WIN32)


#define OS_Windows


#endif


int main(int argc, char *argv[])
{
#ifdef OS_Windows
/* Windows code */
#else
/* GNU/Linux code */
#endif
}

它通常是这样做的(或多或少) :

#ifdef _WIN32
#include <windows.h>
#include <stdio.h>
#include <tchar.h>


#define DIV 1048576
#define WIDTH 7
#endif


#ifdef linux
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#endif




int main(int argc, char *argv[])
{
#ifdef _WIN32
MEMORYSTATUSEX statex;
statex.dwLength = sizeof (statex);
GlobalMemoryStatusEx (&statex);


_tprintf (TEXT("There is  %*ld %% of memory in use.\n"),
WIDTH, statex.dwMemoryLoad);
#endif


#ifdef linux
char cmd[30];
int flag = 0;
FILE *fp;
char line[130];
int TotalMem, TotalFree, TotalUsed;


flag=0;
memcpy (cmd,"\0",30);
sprintf(cmd,"free -t -m|grep Total");
fp = popen(cmd, "r");
while ( fgets( line, sizeof line, fp))
{
flag++;
sscanf(line,"%*s %d %d %d",&TotalMem, &TotalUsed, &TotalFree);
}
pclose(fp);


if(flag)
printf("TotalMem:%d -- TotalUsed:%d -- TotalFree:%d\n",TotalMem,TotalUsed,TotalFree);
else
printf("not found\n");
#endif


return 0;
}

这样,在 linux 平台上只编译 linux 代码,而在 windows 平台上只编译 windows 代码。

您将变量(存在于运行时中)与预处理器符号(仅存在于编译期间)混淆了。

在执行类似于 #define OS_Windows 1的操作之后,就不能使用符号 OS _ Windows 作为变量并将其放入 if()中... ... 我的意思是,您可以这样做,但是在编译到 if (1)期间将对其进行扩展。

对于跨平台项目,你必须使用 ABC0或 #ifdef要确保编译器为给定的操作系统和 只编译那个。选择正确的代码部分

比如:

void openWindow() {
#if OS_Windows
// windows-specific code goes here
#else
// linux-specific code
#endif
}

你的基本策略有很大的缺陷。

通过在 main 函数中使用 if,您可以选择要在 RUNTIME 上运行的代码块。 因此,即使为 unix 编译,编译器仍然必须为 windows 编译代码(这是不能做到的,因为没有包含头文件) ,反之亦然。

相反,您需要 # if,它将在编译时计算,并且不会尝试编译不相关的代码。

所以本质上,您需要理解 if 在运行时计算定义为表达式,而 # if 在编译时计算预定义常量的值。

我在这里看到了很多不同的解决方案,这让我感到不舒服... ... 如果它们在 Linux 上工作,但不能在 Windows 上工作,或者在 Windows 上工作,但不能在 Linux 上工作,那该怎么办?如果它们只能在某些编译器上工作呢?等等。

所以我找到了这个链接,我喜欢: https://web.archive.org/web/20191012035921/http://nadeausoftware.com/articles/2012/01/c_c_tip_how_use_compiler_predefined_macros_detect_operating_system

看起来这些是最好的(使用 # ifdef,# endf 等) :

  • 用于 Windows32位或64位的 _WIN32
  • _WIN64仅适用于 Windows64位
  • 用于 Unix 的 __unix__