Frage #9

Wie unterscheide ich unterschiedliche Betriebssysteme?

Antwort:

In Programmiersprachen, die nicht auf ein bestimmtes Problem spezialisiert sind trifft man immer wieder auf das Problem, dass manche Anforderungen bei einem Betriebssystem anders gelöst werden müssen als bei einem anderen (oder in der Betriebssystemprogrammierung, dass z.B. der Linux-Kernel für unterschiedliche Computer auch unterschiedlich zusammengebaut werden muss). HTML im Gegenzug dazu ist eine spezialisierte Sprache, die auf allen Betriebssystemen gleich laufen soll. In C kann der Aufruf zum Umbenennen einer Datei über die Standard-Library abgedeckt werden. Der Aufruf eines Netzwerksockets ist allerdings in beiden Sprachen unterschiedlich. Wir müssen dies also für Linux und Windows unterschiedlich implementieren.

Um die Betriebssysteme zu unterscheiden kann man mit Hilfe des Präprozessors und vordefinierter Makros unterschieden werden. Je nach Betriebssystem definiert der Compiler passende Makros vor:

Betriebssystem Makro
__linux__ Linux
TARGET_OS_MAC MacOS
_WIN32 32 Bit Windows
_WIN64 64 Bit Windows

Mit dem Präprozessor lässt sich nun eine portable Funktion schreiben, die je nach Betriebssystem unterschiedlich arbeitet.

#include <stdio.h>
 
char const * getOSString()
{
  char const * result;
 
#ifdef __linux__
  /* Anweisungen werden nur unter Linux kompiliert */
 
  result = "linux";
#elif defined TARGET_OS_MAC
  /* Anweisungen werden nur unter MacOS kompiliert */
 
  result = "mac";
#elif defined _WIN32 || defined _WIN64
  /* Anweisungen werden nur unter Windows kompiliert,
     aber unabhängig ob 32- oder 64-Bit Windows */
 
  result = "windows";
#else
  /* Anweisungen werden nur ausgeführt, wenn das OS nicht bekannt ist */
 
  result = "unbekannt";
#endif
  /* Ab hier gilt es wieder für alle Betriebssysteme */
 
  return result;
}
 
int main( void )
{
  printf( "Dein Betriebssystem: %s\n", getOSString() );
 
  return 0;
}

Windows

Regelmäßig sieht man auch folgende Ziele.

#ifdef _WIN32 || _WIN64

Diese wird aber nicht von jedem Compiler akzeptiert, ist damit also nicht zwangsläufig portabel. Mit

#if defined _WIN32 || defined _WIN64

konnte das Problem bisher immer vermieden werden.

Präprozessor abfragen

Mit dem C-Präprozessor „cpp“ lassen sich die vordefinierten Makros einer Datei anzeigen. Wenn Du den oben stehenden Code als „getOSString.c“ abspeicherst und dann

cpp -dM getOSString.c

aufrufst, erhältst Du eine lange Liste mit vordefinierten Makros für diese Datei. Einige interessante habe ich mal herausgepickt:

xin@trinity:~$ cpp -dM getOSString.c
...
#define __unix__ 1
...
#define __linux 1
...
#define __unix 1
...
#define __SIZEOF_INT__ 4
#define __SIZEOF_POINTER__ 8
...
#define __amd64 1
...
#define __LP64__ 1
...
#define unix 1
...
#define __linux__ 1
...
#define __ELF__ 1
...
#define __x86_64__ 1
...
#define NULL ((void *)0)
...
#define linux 1
...
#define __amd64__ 1
...
#define __ULONG32_TYPE unsigned int
...
#define FOPEN_MAX 16
...
#define __INT32_TYPE__ int
#define __SIZEOF_DOUBLE__ 8
...
#define __INT16_C(c) c
...
#define __U32_TYPE unsigned int
#define __STDC__ 1
...

Verbesserungsvorschläge

Hat Dir diese Antwort geholfen? Wenn nicht oder wenn du Verbesserungs- bzw. Erweiterungsvorschläge hast, dann schreib das bitte einfach auf die Diskussionsseite.

Zurück zur FAQ-Übersicht