プリプロセッサディレクティブでOSを確認するにはどうすればよいですか?


194

コードがコンパイルされるオペレーティングシステムに基づいて、さまざまなことを行うためにコードが必要です。私はこのようなものを探しています:

#ifdef OSisWindows
// do Windows-specific stuff
#else
// do Unix-specific stuff
#endif

これを行う方法はありますか?同じことをするより良い方法はありますか?



7
@Cory Klein:いいえ。この質問は何年も前に尋ねられました
John_West

これはおよそあるCではないC++
ilgaar

回答:


288

OSサイトの事前定義マクロには、チェックの完全なリストがあります。それらのいくつかを、それらが見つかった場所へのリンクとともに以下に示します。

ウィンドウズ

_WIN32   32ビットと64ビットの両方
_WIN64    64ビットのみ

Unix(Linux、* BSD、Mac OS X)

このチェックを使用する際のいくつかの落とし穴については、この関連質問を参照してください。

unix
__unix
__unix__

Mac OS X

__APPLE__
__MACH__

両方が定義されています。どちらかをチェックするとうまくいくはずです。

Linux

__linux__
linux 廃止(POSIX準拠ではありません)
__linux廃止(POSIX準拠ではありません)

FreeBSD

__FreeBSD__

アンドロイド

__ANDROID__


1
それはiOSとOS Xの区別することができるように失敗したので、与えられたこのサイトでは、iOSのは含まれていません
ゲイリーマキン

2
Mac OSは定義していません__unix__。なぜあなたはそれをリストに含めますか?
Victor Sergienko、

1
cpp -dM / dev / nullを実行すると、インストールされているgccのバージョンで定義済みのすべてのgccマクロのリストが表示されます
katta

1
Cygwinはunixシンボルを定義し、シンボルを定義しないwin32ので、注意してください。OTOH定義します__CYGWIN__
デビッド・ギブン

__linux__同じ__ANDROID__ですか?
誰も

72

WindowsでGCC定義を表示します。

gcc -dM -E - <NUL:

Linuxの場合:

gcc -dM -E - </dev/null

MinGWの定義済みマクロ:

WIN32 _WIN32 __WIN32 __WIN32__ __MINGW32__ WINNT __WINNT __WINNT__ _X86_ i386 __i386

UNIXの場合:

unix __unix__ __unix

1
WindowsとUnicesだけがOSではありません
phuclv

34

nadeausoftwareLambda Fairyの回答に基づいています

#include <stdio.h>

/**
 * Determination a platform of an operation system
 * Fully supported supported only GNU GCC/G++, partially on Clang/LLVM
 */

#if defined(_WIN32)
    #define PLATFORM_NAME "windows" // Windows
#elif defined(_WIN64)
    #define PLATFORM_NAME "windows" // Windows
#elif defined(__CYGWIN__) && !defined(_WIN32)
    #define PLATFORM_NAME "windows" // Windows (Cygwin POSIX under Microsoft Window)
#elif defined(__ANDROID__)
    #define PLATFORM_NAME "android" // Android (implies Linux, so it must come first)
#elif defined(__linux__)
    #define PLATFORM_NAME "linux" // Debian, Ubuntu, Gentoo, Fedora, openSUSE, RedHat, Centos and other
#elif defined(__unix__) || !defined(__APPLE__) && defined(__MACH__)
    #include <sys/param.h>
    #if defined(BSD)
        #define PLATFORM_NAME "bsd" // FreeBSD, NetBSD, OpenBSD, DragonFly BSD
    #endif
#elif defined(__hpux)
    #define PLATFORM_NAME "hp-ux" // HP-UX
#elif defined(_AIX)
    #define PLATFORM_NAME "aix" // IBM AIX
#elif defined(__APPLE__) && defined(__MACH__) // Apple OSX and iOS (Darwin)
    #include <TargetConditionals.h>
    #if TARGET_IPHONE_SIMULATOR == 1
        #define PLATFORM_NAME "ios" // Apple iOS
    #elif TARGET_OS_IPHONE == 1
        #define PLATFORM_NAME "ios" // Apple iOS
    #elif TARGET_OS_MAC == 1
        #define PLATFORM_NAME "osx" // Apple OSX
    #endif
#elif defined(__sun) && defined(__SVR4)
    #define PLATFORM_NAME "solaris" // Oracle Solaris, Open Indiana
#else
    #define PLATFORM_NAME NULL
#endif

// Return a name of platform, if determined, otherwise - an empty string
const char *get_platform_name() {
    return (PLATFORM_NAME == NULL) ? "" : PLATFORM_NAME;
}

int main(int argc, char *argv[]) {
    puts(get_platform_name());
    return 0;
}

GCCとclangでテスト済み:

  • Debian 8
  • ウィンドウズ(MinGW)
  • Windows(Cygwin)

@MD XF様、Windows、MinGW、Cygwinのバージョンをお知らせください
PADYMKO 2017年

Windows 7 Enterprise 6.1.7601。Cygwin 2.7.0-1。MinGWのバージョンが見つかりませんが、昨日ダウンロードしました。
MD XF 2017年

ただし、このプログラムは標準Cであるため、準拠しているすべてのシステムで動作するはずです。
MD XF 2017年

@MD XF様、この情報をありがとうございます。この回答の上に、あなたを寄稿者として追加しました。
PADYMKO 2017年

10

ほとんどの場合、特定の機能が存在するかどうかを確認することをお勧めします。例:関数pipe()が存在するかどうか。


3
関数が定義されているかどうかを確認する簡単な方法はありますか?
hayalci 2008

1
autoconfigを使用している場合は、AC_CHECK_FUNCS()を使用して関数を確認できます。AC_CHECK_FUNCS(pipe sqrt)は、関数が使用可能な場合、HAVE_PIPEおよびHAVE_SQRTを定義します。他の構築ツールでどうなるかはわかりませんが、これもある意味でサポートしていると思います。
quinmars 2008

@MDXF C ++ 17現在、__ has_includeがあります。まだCで標準化されているとは思いませんが、すべての主要コンパイラ(GCC、Clang、ICC、MSVC)は、Cモードであっても、ベンダー固有の拡張機能として実装しています。
Alcaro


5

Microsoft C / C ++コンパイラ(MSVC)の定義済みマクロは、こちらで確認できます

私はあなたが探していると思います:

  • _WIN32-コンパイルターゲットが32ビットARM、64ビットARM、x86、またはx64の場合、1として定義されます。それ以外の場合、未定義
  • _WIN64-コンパイルターゲットが64ビットARMまたはx64の場合、1として定義されます。それ以外の場合、未定義です。

gccコンパイラの事前定義されたマクロはここにあります

私はあなたが探していると思います:

  • __GNUC__
  • __GNUC_MINOR__
  • __GNUC_PATCHLEVEL__

事前に定義された適切なコンパイラに対してグーグルを実行します。


4

C標準に従って設定された標準マクロはありません。一部のCコンパイラは、一部のプラットフォームで1を設定します(たとえば、Appleのパッチが適用されたGCCは、それがAppleシステムおよびDarwinプラットフォームでコンパイルされていることを示すマクロを設定します)。プラットフォームやCコンパイラでも何かを設定するかもしれませんが、一般的な方法はありません。

hayalciが言ったように、ビルドプロセスでこれらのマクロを何らかの方法で設定するのが最善です。コードを変更せずに、ほとんどのコンパイラでマクロを定義するのは簡単です。あなたは単に-D MACROGCCに渡すことができます、すなわち

gcc -D Windows
gcc -D UNIX

そしてあなたのコードで:

#if defined(Windows)
// do some cool Windows stuff
#elif defined(UNIX)
// do some cool Unix stuff
#else
#    error Unsupported operating system
#endif

4

MinGWでは、_WIN32定義チェックが機能していません。これが解決策です:

#if defined(_WIN32) || defined(__CYGWIN__)
    // Windows (x86 or x64)
    // ...
#elif defined(__linux__)
    // Linux
    // ...
#elif defined(__APPLE__) && defined(__MACH__)
    // Mac OS
    // ...
#elif defined(unix) || defined(__unix__) || defined(__unix)
    // Unix like OS
    // ...
#else
    #error Unknown environment!
#endif

詳細については、https//sourceforge.net/p/predef/wiki/OperatingSystems/をご覧ください。


3
素晴らしいリンク。---
MD XF 2017年

2

OSsymbolが使用され#define OSsymbolている#ifdef OSsymbol場所#defineターゲットOSを特定する」ことができ、シンボル。

通常は、選択したOSシンボルを定義する中央のヘッダーファイルをインクルードし、OS固有のインクルードおよびライブラリディレクトリを使用してコンパイルおよびビルドします。

開発環境を指定していませんが、コンパイラが一般的なプラットフォームとOSのグローバル定義を提供していると確信しています。

http://en.wikibooks.org/wiki/C_Programming/Preprocessorも参照してください


2

2

外部参照については申し訳ありませんが、私はあなたの質問に適していると思います:

C / C ++のヒント:コンパイラの定義済みマクロを使用してオペレーティングシステムの種類を検出する方法


1
そのメタ投稿は削除されました。節度の理由で削除された投稿について尋ねるメタ投稿が節度の理由で削除されたのはおかしい。
MD XF 2017年

:)うん。絶対にクレイジー
bruziuz

2

Boost.Predefは、OS(BOOST_OS_*)を含むターゲットプラットフォーム用のさまざまな定義済みマクロが含まれています。はい、ブーストはC ++ライブラリと見なされることがよくありますが、これはCでも機能するプリプロセッサヘッダーです。

このライブラリは、C、C ++、Objective C、およびObjective C ++の事前定義マクロまたは一般に利用可能なヘッダーで定義されているマクロから収集できる情報から、コンパイラ、アーキテクチャ、オペレーティングシステム、ライブラリ、およびその他のバージョン番号のセットを定義します。このライブラリのアイデアは、Boost Configライブラリを拡張して、サポートする機能定義よりも多くの一貫した情報を提供するという提案から生まれました。以下は、その簡単な提案の編集バージョンです。

例えば

#include <boost/predef.h>

#if defined(BOOST_OS_WINDOWS)
#elif defined(BOOST_OS_ANDROID)
#elif defined(BOOST_OS_LINUX)
#elif defined(BOOST_OS_BSD)
#elif defined(BOOST_OS_AIX)
#elif defined(BOOST_OS_HAIKU)
...
#endif

完全なリストは、BOOST_OSオペレーティングシステムマクロにあります。


1

ここでは俳句の定義が見つかりませんでした。完全に言うと、Haiku-osの定義は単純です__HAIKU__


0

一部のコンパイラは、これを支援する#defineを生成します。コンパイラのドキュメントを読んで、それらが何かを確認してください。MSVCはそれを定義しています__WIN32__GCCはあなたが見ることができるいくつかを持っていますtouch foo.h; gcc -dM foo.h


1
gcc:エラー:認識されないコマンドラインオプション '--show-defines' gcc:致命的なエラー:入力ファイルのコンパイルが終了していません。
Sebi2020

0

プリプロセッサディレクティブ警告またはエラーとして使用して、コンパイル時にチェックすることができます。このプログラムを実行する必要はなく、単にコンパイルするだけです。

#if defined(_WIN32) || defined(_WIN64) || defined(__WINDOWS__)
    #error Windows_OS
#elif defined(__linux__)
    #error Linux_OS
#elif defined(__APPLE__) && defined(__MACH__)
    #error Mach_OS
#elif defined(unix) || defined(__unix__) || defined(__unix)
    #error Unix_OS
#else
    #error Unknown_OS
#endif

#include <stdio.h>
int main(void)
{
    return 0;
}

0

私はあなたが使っているオペレーティングシステムを得るために小さなライブラリを書きました、それはclibを使ってインストールできますあなたのプロジェクトのための依存関係としてそれを使用するのはとても簡単ですので、(Cパッケージマネージャ)。

インストール

$ clib install abranhe/os.c

使用法

#include <stdio.h>
#include "os.h"

int main()
{
    printf("%s\n", operating_system());
    // macOS
    return 0;
}

使用してchar*いるオペレーティングシステムの名前を含む文字列()を返します。このプロジェクトの詳細については、Githubのドキュメントをご覧ください。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.