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

Detect Windows or Linux in C, C++

本文关键字:Windows Linux 检测 c++      更新时间:2023-10-16

我正在写一个跨平台程序。我希望这个程序在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,"",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:%dn",TotalMem,TotalUsed,TotalFree);
        else
            printf("not foundn");
    }
    return 0;
}

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

#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,"",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:%dn",TotalMem,TotalUsed,TotalFree);
else 
    printf("not foundn");
#endif
    return 0;
}

这样,只有linux的代码会在linux平台上编译,只有windows的代码会在windows平台上编译。

您应该在代码中使用相同的#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    
}

我在这里看到了很多不同的解决方案,这让我感到不舒服…如果它们可以在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, #endif等):

  • _WIN32 for Windows 32位或64位
  • _WIN64仅适用于Windows 64位
  • __unix__ for Unix

你混淆了变量(存在于运行时)和预处理器符号(只存在于编译期间)。

在你做了像#define OS_Windows 1这样的事情之后,你不能使用符号OS_Windows作为变量并把它放在if() s中…我的意思是,你可以,但它会在编译过程中扩展到if (1)

对于一个跨平台的项目,你必须使用#if#ifdef 来确保编译器为给定的操作系统选择了正确的代码部分,并且只编译它。

类似:

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

你的基本策略存在严重缺陷。

通过在main函数中使用if,您可以选择在运行时运行的代码块。因此,即使为unix编译,编译器仍然必须为windows构建代码(这是失败的,因为头文件不包括在内),反之亦然。

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

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