Come posso controllare il sistema operativo con una direttiva preprocessore?
-
02-07-2019 - |
Domanda
Ho bisogno del mio codice per fare cose diverse in base al sistema operativo su cui viene compilato. Sto cercando qualcosa del genere:
#ifdef OSisWindows
// do Windows-specific stuff
#else
// do Unix-specific stuff
#endif
C'è un modo per farlo? C'è un modo migliore per fare la stessa cosa?
Soluzione
Il Macro predefinite per sistema operativo ha un elenco molto completo di controlli. Eccone alcuni, con collegamenti a dove sono stati trovati:
Windows
_WIN32
& nbsp; & nbsp; & nbsp; Sia a 32 bit che a 64 bit
_WIN64
& nbsp; & nbsp; & nbsp; solo 64 bit
Unix (Linux, * BSD, Mac OS X)
Vedi questa domanda correlata in alcune delle insidie ??dell'utilizzo di questo controllo.
unix
__ unix
__ unix __
Mac OS X
__ APPLE __
__ MACH __
Entrambi sono definiti; il controllo per entrambi dovrebbe funzionare.
Linux
__ linux __
linux
obsoleto (non conforme a POSIX)
__linux
Obsoleto (non conforme a POSIX)
FreeBSD
__ FreeBSD __
Altri suggerimenti
mostra GCC definisce su Windows:
gcc -dM -E - <NUL:
su Linux:
gcc -dM -E - </dev/null
Macro predefinite in MinGW:
WIN32 _WIN32 __WIN32 __WIN32__ __MINGW32__ WINNT __WINNT __WINNT__ _X86_ i386 __i386
su UNIX:
unix __unix__ __unix
Basato su nadeausoftware e Risposta di 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
char *
get_platform_name() {
return (PLATFORM_NAME == NULL) ? "" : PLATFORM_NAME;
}
int main(int argc, char *argv[]) {
puts(get_platform_name());
return 0;
}
Testato con GCC e clang su:
- Debian 8
- Windows (MinGW)
- Windows (Cygwin)
Nella maggior parte dei casi è meglio verificare se una determinata funzionalità è presente o meno. Ad esempio: se esiste la funzione pipe ()
.
#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
Le macro predefinite del compilatore Microsoft C / C ++ (MSVC) sono disponibili qui:
https://docs.microsoft.com/en-us / cpp / preprocessore / predefinito-macro
Penso che tu stia cercando:
_WIN32 - Definito come 1 quando la destinazione della compilazione è ARM a 32 bit, ARM a 64 bit, x86 o x64. Altrimenti, non definito
_WIN64 - Definito come 1 quando la destinazione della compilazione è ARM a 64 bit o x64. Altrimenti, non definito.
Il compilatore gcc PreDefined MAcros è disponibile qui:
Penso che tu stia cercando:
__ GNUC__
__GNUC_MINOR__
__GNUC_PATCHLEVEL__
Fai un google per i compilatori appropriati predefiniti.
Non esiste una macro standard impostata in base allo standard C. Alcuni compilatori C ne imposteranno uno su alcune piattaforme (ad esempio GCC con patch di Apple imposta una macro per indicare che si sta compilando su un sistema Apple e per la piattaforma Darwin). Anche la tua piattaforma e / o il tuo compilatore C possono impostare qualcosa, ma non esiste un modo generale.
Come ha detto hayalci, è meglio avere queste macro impostate in qualche modo nel processo di compilazione. È facile definire una macro con la maggior parte dei compilatori senza modificare il codice. Puoi semplicemente passare -D MACRO
a GCC, cioè
gcc -D Windows
gcc -D UNIX
E nel tuo codice:
#if defined(Windows)
// do some cool Windows stuff
#elif defined(UNIX)
// do some cool Unix stuff
#else
# error Unsupported operating system
#endif
Su MinGW, il controllo _WIN32
non funziona. Ecco una soluzione:
#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
Per ulteriori informazioni, consultare: https://sourceforge.net/p/predef/ wiki / operatingSystems /
Usa #define OSsymbol
e #ifdef OSsymbol
dove OSsymbol è un simbolo #define
'che identifica il tuo sistema operativo di destinazione.
In genere si dovrebbe includere un file di intestazione centrale che definisce il simbolo del sistema operativo selezionato e utilizzare directory di libreria e di inclusione specifiche del sistema operativo per compilare e creare.
Non hai specificato il tuo ambiente di sviluppo, ma sono abbastanza sicuro che il tuo compilatore fornisca definizioni globali per piattaforme e sistemi operativi comuni.
Vedi anche http://en.wikibooks.org/wiki/C_Programming/Preprocessor
Giusto per riassumere, ecco un mucchio di link utili.
- Macro predefinite comuni GCC
- Sistemi operativi predefiniti di SourceForge
- Macro predefinite MSDN
- La pagina del software Naudea molto collegata
- Wikipedia !!!
- SourceForge's " Panoramica delle macro predefinite del compilatore per standard, compilatori, sistemi operativi e architetture hardware . "
- FreeBSD's " Differencing Operating Systems "
- Tutti i tipi di macro predefinite
-
libportable
Ci scusiamo per il riferimento esterno, ma penso che sia adatto alla tua domanda:
Alcuni compilatori genereranno #define che possono aiutarti in questo. Leggi la documentazione del compilatore per determinare quali sono. MSVC definisce quello che è __WIN32__
, < a href = "https://gcc.gnu.org/onlinedocs/gcc/Preprocessor-Options.html" rel = "nofollow noreferrer"> GCC ce ne sono alcuni che puoi vedere con touch foo.h; gcc -dM foo.h
Puoi utilizzare direttive pre-processore come avviso o errore per verificare in fase di compilazione che non devi eseguire questo programma è semplicemente semplicemente compilalo .
#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;
}
Non ho trovato la Haiku qui. Per essere completo, la definizione di Haiku-os è semplice __HAIKU__
Puoi utilizzare Boost.Predef
che contiene varie macro predefinite per la piattaforma di destinazione incluso il sistema operativo. Sì, boost è spesso pensato come una libreria C ++, ma questa è un'intestazione del preprocessore che funziona anche con C
Questa libreria definisce un set di compilatore, architettura, sistema operativo, libreria e altri numeri di versione dalle informazioni che può raccogliere di macro predefinite C, C ++, Objective C e Objective C ++ o quelle definite nelle intestazioni generalmente disponibili. L'idea di questa libreria è nata da una proposta di estensione della libreria Boost Config per fornire informazioni più e coerenti rispetto alle definizioni delle funzionalità supportate. Quella che segue è una versione modificata di quella breve proposta.
Ad esempio
#include <boost/predef.h>
#if defined(BOOST_OS_WINDOWS)
#elif defined(BOOST_OS_ANDROID)
#elif defined(BOOST_OS_LINUX)
#elif defined(BOOST_OS_BSD)
...
#endif
Ho scritto una piccola libreria per ottenere il sistema operativo in cui ti trovi, può essere installato usando clib (Il gestore di pacchetti C), quindi è davvero semplice usarlo come dipendenza per i tuoi progetti.
install
$ clib install abranhe/os.c
Uso
#include <stdio.h>
#include "os.h"
int main()
{
printf("%s\n", operating_system());
// macOS
return 0;
}
Restituisce una stringa ( char *
) con il nome del sistema operativo che stai utilizzando, per ulteriori informazioni su questo progetto consulta la documentazione su Github .