كيف يمكنني التحقق من نظام التشغيل باستخدام توجيهات المعالج المسبق؟

StackOverflow https://stackoverflow.com/questions/142508

سؤال

أحتاج إلى الكود الخاص بي للقيام بأشياء مختلفة بناءً على نظام التشغيل الذي يتم تجميعه عليه.أنا أبحث عن شيء مثل هذا:

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

هل هناك طريقة للقيام بذلك؟هل هناك طريقة أفضل لفعل الشيء نفسه؟

هل كانت مفيدة؟

المحلول

ال وحدات الماكرو المحددة مسبقًا لنظام التشغيل يحتوي الموقع على قائمة كاملة جدًا من الشيكات.فيما يلي عدد قليل منها، مع روابط لمكان العثور عليها:

شبابيك

_WIN32كلا 32 بت و 64 بت
_WIN6464 بت فقط

يونكس (لينكس، *BSD، نظام التشغيل Mac OS X)

انظر الى هذا سؤال ذو صلة على بعض مخاطر استخدام هذا الفحص.

unix
__unix
__unix__

ماك أو إس إكس

__APPLE__
__MACH__

كلاهما محدد.التحقق من أي منهما يجب أن يعمل.

لينكس

__linux__
linux قديم (غير متوافق مع POSIX)
__linux قديم (غير متوافق مع POSIX)

فري بي إس دي

__FreeBSD__

نصائح أخرى

عرض تعريفات مجلس التعاون الخليجي على نظام التشغيل Windows:

gcc -dM -E - <NUL:

على لينكس:

gcc -dM -E - </dev/null

وحدات الماكرو المحددة مسبقًا في MinGW:

WIN32 _WIN32 __WIN32 __WIN32__ __MINGW32__ WINNT __WINNT __WINNT__ _X86_ i386 __i386

على أنظمة التشغيل UNIX:

unix __unix__ __unix

مرتكز على com.nadeausoftware و إجابة لامدا فيري.

#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;
}

تم اختباره مع دول مجلس التعاون الخليجي ورن على:

  • ديبيان 8
  • ويندوز (مينغو)
  • ويندوز (سيجوين)

في معظم الحالات، من الأفضل التحقق من وجود وظيفة معينة أم لا.على سبيل المثال:إذا كانت الوظيفة 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

يمكن العثور على وحدات الماكرو المحددة مسبقًا لمترجم Microsoft C/C++ (MSVC) هنا:

https://docs.microsoft.com/en-us/cpp/preprocessor/preتعريف-macros

أعتقد أنك تبحث عن:

_WIN32 - يتم تعريفه على أنه 1 عندما يكون هدف التحويل البرمجي هو 32 بت ARM، أو 64 بت ARM، أو x86، أو x64.وإلا غير محدد
_WIN64 - يتم تعريفه بالرقم 1 عندما يكون هدف التحويل البرمجي هو 64 بت ARM أو x64.وإلا غير محدد.

يمكن العثور على وحدات MACROs المحددة مسبقًا لمترجم gcc هنا:

http://gcc.gnu.org/onlinedocs/cpp/Preident-Macros.html

أعتقد أنك تبحث عن:

__GNUC__
__GNUC_MINOR__
__GNUC_PATCHLEVEL__

قم بإجراء بحث في Google عن المترجمين المناسبين المحددين مسبقًا.

لا يوجد ماكرو قياسي تم تعيينه وفقًا لمعيار C.سيقوم بعض مترجمي لغة C بتعيين واحد على بعض الأنظمة الأساسية (على سبيل المثال.تقوم مجموعة دول مجلس التعاون الخليجي المصححة من Apple بتعيين ماكرو للإشارة إلى أنه يتم تجميعها على نظام Apple ومنصة Darwin).قد يقوم النظام الأساسي الخاص بك و/أو مترجم C الخاص بك بتعيين شيء ما أيضًا، ولكن لا توجد طريقة عامة.

كما قال Hayalci، من الأفضل تعيين وحدات الماكرو هذه في عملية الإنشاء بطريقة أو بأخرى.من السهل تحديد ماكرو باستخدام معظم المترجمين دون تعديل الكود.يمكنك ببساطة المرور -D MACRO إلى دول مجلس التعاون الخليجي، أي.

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

في 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/

يستخدم #define OSsymbol و #ifdef OSsymbolحيث OSsymbol هو #define'رمز قادر على تحديد نظام التشغيل المستهدف الخاص بك.

عادةً ما تقوم بتضمين ملف رأس مركزي يحدد رمز نظام التشغيل المحدد واستخدام أدلة التضمين والمكتبة الخاصة بنظام التشغيل للتجميع والإنشاء.

لم تحدد بيئة التطوير الخاصة بك، ولكنني متأكد تمامًا من أن المترجم الخاص بك يوفر تعريفات عالمية للأنظمة الأساسية وأنظمة التشغيل الشائعة.

أنظر أيضا http://en.wikibooks.org/wiki/C_Programming/Preprocessor

سيقوم بعض المترجمين بإنشاء تعريفات يمكن أن تساعدك في هذا الأمر.اقرأ وثائق المترجم لتحديد ماهيتها. MSVC يحدد واحد هذا __WIN32__, مجلس التعاون الخليجي لديه بعض يمكنك أن ترى مع touch foo.h; gcc -dM foo.h

يمكنك استخدام توجيهات المعالج مثل تحذير أو خطأ للتحقق في وقت الترجمة لا تحتاج إلى ذلك يجري هذا البرنامج على الإطلاق بكل بساطة ترجمة هو - هي .

#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;
}

لم أجد هايكو التعريف هنا.لكي يكون كاملا، تعريف Haiku-os بسيط __HAIKU__

يمكنك استخدام Boost.Predef والذي يحتوي على العديد من وحدات الماكرو المحددة مسبقًا للنظام الأساسي المستهدف بما في ذلك نظام التشغيل.غالبًا ما يُنظر إلى Yes Boost على أنها مكتبة 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)
...
#endif

لقد كتبت مكتبة صغيرة للحصول على نظام التشغيل الذي تستخدمه، يمكن تثبيته باستخدام clib (مدير الحزم C)، لذلك من السهل حقًا استخدامه كتبعية لمشاريعك.

ثَبَّتَ

$ clib install abranhe/os.c

الاستخدام

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

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

تقوم بإرجاع سلسلة (char*) باسم نظام التشغيل الذي تستخدمه، لمزيد من المعلومات حول هذا المشروع قم بمراجعته الوثائق على جيثب.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top