İşletim sistemini bir önişlemci yönergesi ile nasıl kontrol edebilirim?


195

Kodunun derlendiği işletim sistemine göre farklı şeyler yapmak için ihtiyacım var. Ben böyle bir şey arıyorum:

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

Bunu yapmanın bir yolu var mı? Aynı şeyi yapmanın daha iyi bir yolu var mı?



8
@Cory Klein: Hayır-hayır. Bu soru yıllar önce soruldu
John_West

Bu yaklaşık CdeğilC++
ilgaar

Yanıtlar:


290

Ön tanımlı Makro OS için sitesi kontrolleri çok tam listesi vardır. İşte bunlardan birkaçı, bulundukları yerlere bağlantılar:

pencereler

_WIN32
_WIN64   Yalnızca    32 bit ve 64 bit 64 bit

Unix (Linux, * BSD, Mac OS X)

Bu kontrolü kullanmanın bazı zorlukları ile ilgili bu soruya bakın .

unix
__unix
__unix__

Mac OS X

__APPLE__
__MACH__

Her ikisi de tanımlanmıştır; her ikisinin de kontrol edilmesi gerekir.

Linux

__linux__
linux Eski (POSIX uyumlu değil)
__linuxEski (POSIX uyumlu değil)

FreeBSD

__FreeBSD__

Android

__ANDROID__


1
Verilen bu site iOS içermiyor, bu yüzden iOS ve OS X arasında ayrım yapamıyor.
Gary Makin

2
Mac OS tanımlamıyor __unix__. Neden listeye dahil ettiniz?
Victor Sergienko

1
cpp -dM / dev / null, kurulu gcc sürümünüzdeki tüm gcc önceden tanımlanmış makroların bir listesini verecektir
katta

1
Cygwin unixsembolleri tanımlar ve sembolleri tanımlamaz win32, bu yüzden dikkatli olun. OTOH tanımlar __CYGWIN__.
David Verilen

ile __linux__aynı __ANDROID__??
kimse

72

Windows'da GCC tanımlarını göster:

gcc -dM -E - <NUL:

Linux'ta:

gcc -dM -E - </dev/null

MinGW'de önceden tanımlanmış makrolar:

WIN32 _WIN32 __WIN32 __WIN32__ __MINGW32__ WINNT __WINNT __WINNT__ _X86_ i386 __i386

UNIX'lerde:

unix __unix__ __unix

1
Windows ve
Unices

35

Dayanarak nadeausoftware ve Lambda Perinin cevap .

#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 ve clang ile test edilmiştir:

  • Debian 8
  • Windows (MinGW)
  • Windows (Cygwin)

sevgili @MD XF, lütfen Windows, MinGW ve Cygwin sürümlerinizi
belirtin

Windows 7 Enterprise 6.1.7601. Cygwin 2.7.0-1. MinGW sürümünü bulamıyorum ama dün indirdim.
MD XF

Muhtemelen farkında olmalısınız - bu program standart C'dir, bu nedenle tüm uyumlu sistemlerde çalışmalıdır.
MD XF

sevgili @MD XF, bu bilgi için teşekkür ederim. Sizi bu cevabın üstüne katkıda bulundum.
PADYMKO

10

Çoğu durumda, belirli bir işlevin var olup olmadığını kontrol etmek daha iyidir. Örneğin: işlev pipe()varsa veya mevcut değilse.


3
bir fonksiyonun tanımlanıp tanımlanmadığını kontrol etmenin kolay bir yolu var mı?
hayalci

1
Otomatik yapılandırma kullanıyorsanız, AC_CHECK_FUNCS () işlevlerini kontrol edebilirsiniz. AC_CHECK_FUNCS (boru sqrt), fonksiyonlar mevcutsa HAVE_PIPE ve HAVE_SQRT tanımlayacaktır. Diğer yapı araçlarıyla nasıl olduğunu bilmiyorum, ama sanırım bunu da bir şekilde destekliyorlar.
quinmars

@ MDXF C ++ 17 itibarıyla __has_include vardır. Henüz C'de standartlaştırıldığını düşünmüyorum, ancak tüm büyük derleyiciler (GCC, Clang, ICC, MSVC) C modunda bile satıcıya özgü bir uzantı olarak uyguluyor.
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

5

Microsoft C / C ++ derleyici (MSVC) Önceden Tanımlı Makrolar bulunabilir burada

Sanırım aradığınız:

  • _WIN32- Derleme hedefi 32 bit ARM, 64 bit ARM, x86 veya x64 olduğunda 1 olarak tanımlanır. Aksi takdirde, tanımsız
  • _WIN64- Derleme hedefi 64 bit ARM veya x64 olduğunda 1 olarak tanımlanır. Aksi takdirde, tanımsız.

gcc derleyici PreDefined MAcros bulunabilir burada

Sanırım aradığınız:

  • __GNUC__
  • __GNUC_MINOR__
  • __GNUC_PATCHLEVEL__

Önceden tanımlanmış uygun derleyicileriniz için bir google yapın.


4

C standardına göre ayarlanmış standart bir makro yoktur. Bazı C derleyicileri bazı platformlarda bir tane kurar (örneğin Apple'ın yamalı GCC'si, bir Apple sisteminde ve Darwin platformu için derlendiğini belirtmek için bir makro ayarlar). Platformunuz ve / veya C derleyiciniz de bir şey ayarlayabilir, ancak genel bir yolu yoktur.

Hayalci'nin dediği gibi, bu makroların bir şekilde oluşturma işleminizde olması en iyisidir. Kodu değiştirmeden çoğu derleyiciye sahip bir makro tanımlamak kolaydır. Sadece GCC'ye geçebilirsiniz -D MACRO, yani

gcc -D Windows
gcc -D UNIX

Ve kodunuzda:

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

4

MinGW'de tanım _WIN32denetimi çalışmıyor. İşte bir çözüm:

#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

Daha fazla bilgi için lütfen bakınız: https://sourceforge.net/p/predef/wiki/OperatingSystems/


3
Harika bağlantı. ---
MD XF

2

Kullanım #define OSsymbolve #ifdef OSsymbol OSsymbol bir#define hedef OS belirleme 'mümkün sembolü.

Genellikle, seçili OS sembolünü tanımlayan merkezi bir başlık dosyası ekler ve derlemek ve derlemek için OS'ye özgü include ve kütüphane dizinlerini kullanırsınız.

Geliştirme ortamınızı belirtmediniz, ancak derleyicinizin ortak platformlar ve işletim sistemleri için küresel tanımlar sağladığından eminim.

Ayrıca bkz. Http://en.wikibooks.org/wiki/C_Programming/Preprocessor


2


2

Boost.PredefOS ( BOOST_OS_*) dahil olmak üzere hedef platform için önceden tanımlanmış çeşitli makrolar içeren seçenekleri kullanabilirsiniz . Evet boost genellikle bir C ++ kütüphanesi olarak düşünülür, ancak bu , C ile de çalışan bir önişlemci başlığıdır !

Bu kütüphane C, C ++, Objective C ve Objective C ++ önceden tanımlanmış makrolardan veya genel olarak mevcut başlıklarda tanımlananlardan derleyici, mimari, işletim sistemi, kütüphane ve diğer sürüm numaralarını tanımlar. Bu kütüphane fikri, Boost Config kütüphanesini desteklediği özellik tanımlarından daha fazla ve tutarlı bilgi sağlayacak şekilde genişletme önerisinden doğmuştur. Aşağıda, bu kısa teklifin düzenlenmiş bir sürümüdür.

Örneğin

#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

Tam liste BOOST_OSişletim sistemi makrolarında bulunabilir


1

Haiku'nun tanımını burada bulamadım . Tamamlamak gerekirse, Haiku-os tanımı basittir__HAIKU__


0

Bazı derleyiciler bu konuda size yardımcı olabilecek #defines oluşturur. Ne olduklarını belirlemek için derleyici belgelerini okuyun. MSVC__WIN32__ , GCC'nin görebileceğiniz bazılarını tanımlartouch foo.h; gcc -dM foo.h


1
gcc: hata: tanınmayan komut satırı seçeneği '--show-defines' gcc: ölümcül hata: giriş dosyaları derlemesi sonlanmadı.
Sebi2020

0

Sen kullanabilirsiniz ön işlemci direktifleri olarak uyarı veya hata size gerekmez derleme sırasında kontrol etmek çalıştırmak sadece basitçe hiç bu programı derlemek bunu.

#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

Bulunduğunuz işletim sistemini almak için küçük bir kütüphane yazdım , clib (C paket yöneticisi) kullanılarak kurulabilir , bu yüzden projeleriniz için bir bağımlılık olarak kullanmak gerçekten basittir.

Yüklemek

$ clib install abranhe/os.c

kullanım

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

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

Kullandığınız char*işletim sisteminin adıyla bir dize ( ) döndürür , bu proje hakkında daha fazla bilgi için Github'daki belgelere bakın .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.