Wie überprüfe ich das Betriebssystem mit einer Präprozessoranweisung?

194

Ich brauche meinen Code, um verschiedene Dinge zu tun, basierend auf dem Betriebssystem, auf dem er kompiliert wird. Ich suche so etwas:

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

Gibt es eine Möglichkeit, dies zu tun? Gibt es einen besseren Weg, um das Gleiche zu tun?

Perimosocordiae
quelle
1
Mögliches Duplikat der C ++ - Kompilierung unter Windows und Linux: ifdef switch
Cory Klein
7
@Cory Klein: Nein-nein. Diese Frage wurde Jahre zuvor gestellt
John_West
Dies ist über CnichtC++
ilgaar

Antworten:

288

Die Site Vordefinierte Makros für das Betriebssystem enthält eine sehr vollständige Liste der Überprüfungen. Hier sind einige davon mit Links zu ihrem Fundort:

Windows

_WIN32
_WIN64   Nur    32-Bit- und 64-Bit- 64-Bit

Unix (Linux, * BSD, Mac OS X)

In dieser verwandten Frage finden Sie einige Fallstricke bei der Verwendung dieser Prüfung.

unix
__unix
__unix__

Mac OS X

__APPLE__
__MACH__

Beide sind definiert; Überprüfen, ob beides funktioniert.

Linux

__linux__
linux Veraltet (nicht POSIX-konform)
__linuxVeraltet (nicht POSIX-konform)

FreeBSD

__FreeBSD__

Android

__ANDROID__

Lambda-Fee
quelle
1
Diese Seite enthält kein iOS, daher kann sie nicht zwischen iOS und OS X unterscheiden.
Gary Makin
2
Mac OS definiert nicht __unix__. Warum würden Sie es in die Liste aufnehmen?
Victor Sergienko
1
cpp -dM / dev / null gibt Ihnen eine Liste aller vordefinierten gcc-Makros in Ihrer Version von installiertem gcc
katta
1
Cygwin definiert die unixSymbole und definiert sie nicht. Seien Sie win32also vorsichtig. OTOH definiert es __CYGWIN__.
David gegeben
ist das __linux__gleiche wie __ANDROID__??
niemand
72

show GCC definiert unter Windows:

gcc -dM -E - <NUL:

unter Linux:

gcc -dM -E - </dev/null

Vordefinierte Makros in MinGW:

WIN32 _WIN32 __WIN32 __WIN32__ __MINGW32__ WINNT __WINNT __WINNT__ _X86_ i386 __i386

unter UNIX:

unix __unix__ __unix
qwer
quelle
1
Windows und Unices sind nicht die einzigen Betriebssysteme
phuclv
34

Basierend auf Nadeausoftware und der Antwort von Lambda 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;
}

Getestet mit GCC und klirrend an:

  • Debian 8
  • Windows (MinGW)
  • Windows (Cygwin)
PADYMKO
quelle
das liebe @MD XF, bitte geben Sie Versionen Ihres Windows, MinGW und Cygwin
PADYMKO
Windows 7 Enterprise 6.1.7601. Cygwin 2.7.0-1. Ich kann die MinGW-Version nicht finden, habe sie aber gestern heruntergeladen.
MD XF
Sie sollten jedoch darauf aufmerksam gemacht werden - dieses Programm ist Standard C, daher sollte es auf allen kompatiblen Systemen funktionieren.
MD XF
Lieber @MD XF, danke für diese Information. Ich habe Sie als Mitwirkenden zu dieser Antwort hinzugefügt.
PADYMKO
10

In den meisten Fällen ist es besser zu überprüfen, ob eine bestimmte Funktionalität vorhanden ist oder nicht. Zum Beispiel: ob die Funktion pipe()existiert oder nicht.

Quinmars
quelle
3
Gibt es eine einfache Möglichkeit, herauszufinden, ob eine Funktion definiert ist?
Hayalci
1
Wenn Sie autoconfig verwenden, können Sie mit AC_CHECK_FUNCS () nach Funktionen suchen. AC_CHECK_FUNCS (Pipe sqrt) definiert HAVE_PIPE und HAVE_SQRT, wenn die Funktionen verfügbar sind. Ich weiß nicht, wie es mit anderen Bauwerkzeugen ist, aber ich denke, sie unterstützen dies auch in gewisser Weise.
Quinmars
@MDXF Ab C ++ 17 gibt es __has_include. Ich denke, es ist noch nicht in C standardisiert, aber alle großen Compiler (GCC, Clang, ICC, MSVC) implementieren es als herstellerspezifische Erweiterung, selbst im C-Modus.
Alcaro
7
#ifdef _WIN32
// do something for windows like include <windows.h>
#elif defined __unix__
// do something for unix like include <unistd.h>
#elif defined __APPLE__
// do something for mac
#endif
Arjun Sreedharan
quelle
5

Microsoft C / C ++ - Compiler (MSVC) Vordefinierte Makros finden Sie hier

Ich denke du suchst:

  • _WIN32- Definiert als 1, wenn das Kompilierungsziel 32-Bit-ARM, 64-Bit-ARM, x86 oder x64 ist. Ansonsten undefiniert
  • _WIN64- Definiert als 1, wenn das Kompilierungsziel 64-Bit-ARM oder x64 ist. Ansonsten undefiniert.

gcc compiler PreDefined MAcros finden Sie hier

Ich denke du suchst:

  • __GNUC__
  • __GNUC_MINOR__
  • __GNUC_PATCHLEVEL__

Führen Sie eine Google-Suche nach den entsprechenden vordefinierten Compilern durch.

Martin York
quelle
4

Es gibt kein Standardmakro, das gemäß dem C-Standard eingestellt ist. Einige C-Compiler legen auf einigen Plattformen einen fest (z. B. setzt das gepatchte GCC von Apple ein Makro, um anzuzeigen, dass es auf einem Apple-System und für die Darwin-Plattform kompiliert wird). Ihre Plattform und / oder Ihr C-Compiler stellen möglicherweise auch etwas ein, aber es gibt keinen allgemeinen Weg.

Wie Hayalci sagte, ist es am besten, diese Makros irgendwie in Ihrem Erstellungsprozess zu haben. Mit den meisten Compilern ist es einfach, ein Makro zu definieren, ohne den Code zu ändern. Sie können einfach -D MACROan GCC übergeben, dh

gcc -D Windows
gcc -D UNIX

Und in Ihrem Code:

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

In MinGW _WIN32funktioniert die Definitionsprüfung nicht. Hier ist eine Lösung:

#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

Weitere Informationen finden Sie unter: https://sourceforge.net/p/predef/wiki/OperatingSystems/

Anakod
quelle
3
Toller Link. ---
MD XF
2

Verwenden Sie #define OSsymbolund #ifdef OSsymbol wo OSsymbol ein fähiges #defineSymbol ist, das Ihr Zielbetriebssystem identifiziert.

Normalerweise fügen Sie eine zentrale Header-Datei hinzu, die das ausgewählte Betriebssystemsymbol definiert, und verwenden zum Kompilieren und Erstellen betriebssystemspezifische Include- und Bibliotheksverzeichnisse.

Sie haben Ihre Entwicklungsumgebung nicht angegeben, aber ich bin mir ziemlich sicher, dass Ihr Compiler globale Definitionen für gängige Plattformen und Betriebssysteme bereitstellt.

Siehe auch http://en.wikibooks.org/wiki/C_Programming/Preprocessor

devio
quelle
2

Um alles zusammenzufassen, hier sind einige hilfreiche Links.

MD XF
quelle
2

Sie können Boost.Predefverschiedene vordefinierte Makros für die Zielplattform einschließlich des Betriebssystems ( BOOST_OS_*) verwenden. Ja, Boost wird oft als C ++ - Bibliothek angesehen, aber dies ist ein Präprozessor-Header, der auch mit C funktioniert!

Diese Bibliothek definiert eine Reihe von Compiler-, Architektur-, Betriebssystem-, Bibliotheks- und anderen Versionsnummern aus den Informationen, die sie aus vordefinierten C-, C ++ -, Objective C- und Objective C ++ - oder in allgemein verfügbaren Headern definierten Makros sammeln kann. Die Idee für diese Bibliothek entstand aus einem Vorschlag, die Boost Config-Bibliothek zu erweitern, um mehr und konsistente Informationen als die von ihr unterstützten Feature-Definitionen bereitzustellen. Was folgt, ist eine bearbeitete Version dieses kurzen Vorschlags.

Beispielsweise

#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

Die vollständige Liste finden Sie in den BOOST_OSBetriebssystemmakros

phuclv
quelle
1

Ich habe hier keine Haiku- Definition gefunden. Um vollständig zu sein, ist die Haiku-os-Definition einfach__HAIKU__

TadejP
quelle
0

Einige Compiler generieren #defines, die Ihnen dabei helfen können. Lesen Sie die Compiler-Dokumentation, um festzustellen, um welche es sich handelt. MSVC definiert eine, die __WIN32__, GCC einige hat man mit sehen könnentouch foo.h; gcc -dM foo.h

davenpcj
quelle
1
gcc: Fehler: nicht erkannte Befehlszeilenoption '--show-defined' gcc: schwerwiegender Fehler: Die Kompilierung der Eingabedateien wurde nicht beendet.
Sebi2020
0

Sie können Pre-Prozessor-Direktiven als verwenden Warnung oder Fehler verwenden , um zu überprüfen, ob Siedieses Programm zurKompilierungszeit überhaupt nicht ausführen müssen. Kompilieren Sie eseinfach.

#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;
}
HaSeeB MiR
quelle
0

Ich habe eine geschrieben kleine Bibliothek geschrieben , um das Betriebssystem zu erhalten, auf dem Sie sich befinden. Sie kann mit clib (The C package manager) installiert werden , sodass es sehr einfach ist, sie als Abhängigkeit für Ihre Projekte zu verwenden.

Installieren

$ clib install abranhe/os.c

Verwendung

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

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

Es gibt eine Zeichenfolge ( char*) mit dem Namen des verwendeten Betriebssystems zurück. Weitere Informationen zu diesem Projekt finden Sie in der Dokumentation zu Github .

Abraham Hernandez
quelle