web-dev-qa-db-ja.com

C、C ++でWindowsまたはLinuxを検出

私はクロスプラットフォームプログラムを書いています。この1つのプログラムをWindowsとLinuxの両方で実行したいので、2つのプラットフォーム用に2つの異なるコードセグメントがあります。 OSがWindowsの場合、最初のコードセグメントを実行します。 Linuxの場合、2番目のコードセグメントを実行する必要があります。

そこで、私は次のコードを書きましたが、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;
}
45
Ronin

通常、次のように行われます(多かれ少なかれ)。

#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コードのみがコンパイルされます。

48
user703016

コードでif(OS_Windows)ロジックの代わりに同じ#ifdefを使用する必要があります。

#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    
}
18
Zaur Nasibov

ここにはさまざまな解決策がたくさんありますが、それは私を不快にさせます...それらがLinuxでは動作するがWindowsではなく、Windowsでは動作するがLinuxでは動作しない場合はどうなりますか?一部のコンパイラでのみ動作する場合はどうなりますか?等。

だから私はこのリンクを見つけました、私は好きです: http://nadeausoftware.com/articles/2012/01/c_c_tip_how_use_compiler_predefined_macros_detect_operating_system

これらは最高のようです(#ifdef、#endifなどを使用):

  • _WIN32 Windows 32ビットの場合
  • _WIN64 Windows 64ビットの場合
  • __unix__ for Unix
11
Andrew

変数(実行時に存在する)とプリプロセッサシンボル(コンパイル中にのみ存在する)を混同しています。

_#define OS_Windows 1_のようなことをした後、シンボルOS_Windowsを変数として使用してif() s内に配置することはできません...つまり、できますが、コンパイル中に展開されますif (1)

クロスプラットフォームプロジェクトの場合、_#if_または_#ifdef_を使用して、コンパイラが特定のOSのコードの正しい部分を選択することを確認する必要があります。そしてはそれだけをコンパイルします。

何かのようなもの:

_void openWindow() {
#if OS_Windows
    // windows-specific code goes here
#else
    // linux-specific code
#endif
}
_
7
Kos

あなたの基本戦略は非常に欠陥があります。

メイン関数でifを使用すると、RUNTIMEで実行するコードのチャンクを選択できます。したがって、Unix用にコンパイルする場合でも、コンパイラはWindows用のコードをビルドする必要があります(ヘッダーファイルが含まれていないため実行できません)。

代わりに、コンパイル時に評価され、無関係なコードをコンパイルしようとしない#ifが必要でした。

したがって、本質的には、ifは実行時に式として定義を評価するのに対し、#ifはコンパイル時に定義済み定数の値を評価することを理解する必要があります。

2
Elemental