C++ 在C、C和x2B中检测Windows或Linux+;

C++ 在C、C和x2B中检测Windows或Linux+;,c++,c,windows,linux,C++,C,Windows,Linux,我正在写一个跨平台的程序。我希望这一个程序同时在Windows和Linux下运行,因此我有两个不同的代码段用于这两个平台。如果操作系统是Windows,我希望运行第一个代码段;如果是Linux,那么我希望运行第二个代码段 因此,我编写了以下代码,但在Windows和Linux上构建时都会出错。我该怎么解决它 #ifdef __unix__ /* __unix__ is usually defined by compilers targeting Unix s

我正在写一个跨平台的程序。我希望这一个程序同时在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;
}
#ifdef uuuuuuuuuuuu/*uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu通常由针对unix系统的编译器定义*/
#定义OS_Windows 0
#包括
#包括
#包括
#包括
#elif定义(_WIN32)|定义(WIN32)/*_WIN32通常由针对32位或64位Windows系统的编译器定义*/
#定义OS_Windows 1
#包括
#包括
#包括
#定义分区1048576
#定义宽度7
#恩迪夫
int main(int argc,char*argv[])
{
如果(操作系统窗口)
{
Memorystaturex statex;
statex.dwLength=sizeof(statex);
GlobalMemoryStatusEx(&statex);
_tprintf(TEXT(“有%*ld%%个内存在使用中。\n”),
宽度,statex.dwMemoryLoad);
}
else if(!OS_Windows)//如果操作系统是unix
{
char-cmd[30];
int标志=0;
文件*fp;
字符行[130];
int memTotal、memFree、memUsed;
flag=0;
memcpy(cmd,“\0”,30);
sprintf(cmd,“free-t-m | grep Total”);
fp=popen(cmd,“r”);
而(fgets(生产线、生产线尺寸、fp))
{
flag++;
sscanf(行“%*s%d%d%d”、&TotalMem、&TotalUsed、&TotalFree);
}
pclose(fp);
国际单项体育联合会(旗)
printf(“TotalMem:%d--TotalUsed:%d--TotalFree:%d\n”,TotalMem,TotalUsed,TotalFree);
其他的
printf(“未找到”);
}
返回0;
}

您应该在代码中使用相同的
#ifdef
而不是
if(操作系统窗口)
逻辑:

#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\u WIN32
#包括
#包括
#包括
#定义分区1048576
#定义宽度7
#恩迪夫
#ifdef linux
#包括
#包括
#包括
#包括
#恩迪夫
int main(int argc,char*argv[])
{
#ifdef_WIN32
Memorystaturex statex;
statex.dwLength=sizeof(statex);
GlobalMemoryStatusEx(&statex);
_tprintf(TEXT(“有%*ld%%个内存在使用中。\n”),
宽度,statex.dwMemoryLoad);
#恩迪夫
#ifdef linux
char-cmd[30];
int标志=0;
文件*fp;
字符行[130];
int TotalMem、TotalFree、TotalUsed;
flag=0;
memcpy(cmd,“\0”,30);
sprintf(cmd,“free-t-m | grep Total”);
fp=popen(cmd,“r”);
而(fgets(生产线、生产线尺寸、fp))
{   
flag++;
sscanf(行“%*s%d%d%d”、&TotalMem、&TotalUsed、&TotalFree);
}
pclose(fp);
国际单项体育联合会(旗)
printf(“TotalMem:%d--TotalUsed:%d--TotalFree:%d\n”,TotalMem,TotalUsed,TotalFree);
其他的
printf(“未找到”);
#恩迪夫
返回0;
}

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

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

执行类似于
#定义OS_Windows 1
的操作后,不能将符号OS_Windows用作变量并将其放入
if()
s中。。。我的意思是,您可以,但是在编译过程中,如果(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在编译时计算预定义常量的值。

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

所以我找到了这个链接,我喜欢:

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

  • \u WIN32
    适用于Windows 32位
  • \u WIN64
    适用于Windows 64位
  • 用于unix的unix

什么类型的错误?发生这种情况是因为编译器正在查找
MemoryStatuex
,因为
如果(OS_Windows)
检查不是预处理器检查,它会在运行时发生,因此,在
if
项下的所有内容都必须编译。@RRR请记住勾选答案旁边最能解决您的问题的勾号,这就是我们如何将问题标记为已解决的。也请用你的其他问题来做:-存在跨平台的C++库,比如Qt。通过它的QtCore模块,您可以在Linux、MacOSX和Windows之间移植非图形化应用程序的代码。@RRR我保证
memcpy(cmd,“\0”,30)
不会达到您期望的效果。使用
memset(cmd,'\0',30)
任何值得使用的优化编译器都会删除
if(0)
块。@Dave不幸的是,这并没有真正的帮助,因为编译器无法优化它无法编译的任何内容。我的意思是,问题不是无关的符号;它是不存在的。@Dave同样,任何称职的编译器在
-O0
时也不会删除
if(0)
。thankzzz。。。。你是一个救生员。@Cicada要使编译此代码更改为int memTotal,memFree
void openWindow() {
#if OS_Windows
    // windows-specific code goes here
#else
    // linux-specific code
#endif
}