ฉันจะตรวจสอบระบบปฏิบัติการด้วยคำสั่งพรีโปรเซสเซอร์ได้อย่างไร


195

ฉันต้องการรหัสของฉันเพื่อทำสิ่งต่าง ๆ ตามระบบปฏิบัติการที่ได้รับการรวบรวม ฉันกำลังมองหาบางสิ่งเช่นนี้:

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

มีวิธีทำเช่นนี้หรือไม่? มีวิธีที่ดีกว่าในการทำสิ่งเดียวกันหรือไม่?


1
ซ้ำซ้อนที่เป็นไปได้ของการคอมไพล์ C ++ บน Windows และ Linux: ifdef switch
Cory Klein

8
@Cory Klein: ไม่ไม่ คำถามนี้ถูกถามเมื่อหลายปีก่อน
John_West

นี่เป็นเรื่องเกี่ยวกับCไม่ได้C++
ilgaar

คำตอบ:


290

เว็บไซต์มาโครที่กำหนดล่วงหน้าสำหรับระบบปฏิบัติการมีรายการตรวจสอบที่สมบูรณ์มาก นี่คือตัวอย่างบางส่วนที่มีลิงก์ไปยังที่ที่พบ:

ของ windows

_WIN32   ทั้ง 32 บิตและ 64 บิต
_WIN64   64 บิตเท่านั้น

Unix (Linux, * BSD, Mac OS X)

ดูคำถามที่เกี่ยวข้องกับข้อผิดพลาดในการใช้เช็คนี้

unix
__unix
__unix__

Mac OS X

__APPLE__
__MACH__

ทั้งสองถูกกำหนดไว้; การตรวจสอบอย่างใดอย่างหนึ่งควรทำงาน

ลินุกซ์

__linux__
linux เลิกใช้แล้ว (ไม่เป็นไปตาม POSIX)
__linuxเลิกใช้แล้ว (ไม่ตรงตาม POSIX)

FreeBSD

__FreeBSD__

Android

__ANDROID__


1
ไซต์นี้ไม่รวมถึง iOS ดังนั้นจึงไม่สามารถแยกแยะความแตกต่างระหว่าง iOS และ OS X ได้
Gary Makin

2
Mac OS ไม่ได้กำหนด__unix__ไว้ ทำไมคุณถึงรวมไว้ในรายการ?
Victor Sergienko

1
cpp -dM / dev / null จะให้รายการของแมโครทั้งหมดที่กำหนดไว้ล่วงหน้า gcc ใน gcc รุ่นที่ติดตั้งของคุณ
katta

1
Cygwin กำหนดunixสัญลักษณ์และไม่ได้กำหนดสัญลักษณ์win32ดังนั้นโปรดใช้ความระมัดระวัง OTOH __CYGWIN__มันไม่กำหนด
เดวิดให้

เป็น__linux__เช่นเดียว__ANDROID__??
ไม่มีใคร

72

แสดง GCC ที่กำหนดบน Windows:

gcc -dM -E - <NUL:

บน Linux:

gcc -dM -E - </dev/null

มาโครที่กำหนดไว้ล่วงหน้าใน MinGW:

WIN32 _WIN32 __WIN32 __WIN32__ __MINGW32__ WINNT __WINNT __WINNT__ _X86_ i386 __i386

บน UNIXes:

unix __unix__ __unix

1
Windows และ Unices ไม่ใช่
OS

35

ขึ้นอยู่กับ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
const char *get_platform_name() {
    return (PLATFORM_NAME == NULL) ? "" : PLATFORM_NAME;
}

int main(int argc, char *argv[]) {
    puts(get_platform_name());
    return 0;
}

ทดสอบกับ GCC และส่งเสียงดังกราวบน:

  • เดเบียน 8
  • Windows (MinGW)
  • Windows (Cygwin)

ที่รัก @MD XF โปรดระบุรุ่นของ Windows, MinGW และ Cygwin ของคุณ
PADYMKO

Windows 7 Enterprise 6.1.7601 Cygwin 2.7.0-1 ฉันหาเวอร์ชั่น MinGW ไม่ได้ แต่ฉันดาวน์โหลดเมื่อวานนี้
MD XF

คุณควรทราบว่า - โปรแกรมนี้เป็นมาตรฐาน C ดังนั้นควรทำงานกับระบบที่เข้ากันได้ทั้งหมด
MD XF

เรียน @MD XF ขอบคุณสำหรับข้อมูลนี้ ฉันเพิ่มคุณในฐานะผู้มีส่วนร่วมด้านบนคำตอบนี้
PADYMKO

10

ในกรณีส่วนใหญ่จะเป็นการดีกว่าที่จะตรวจสอบว่ามีฟังก์ชันการทำงานที่มีอยู่หรือไม่ ตัวอย่างเช่น: ถ้าฟังก์ชั่นpipe()มีอยู่หรือไม่


3
มีวิธีที่ง่ายในการตรวจสอบว่าฟังก์ชั่นมีการกำหนดหรือไม่?
hayalci

1
หากคุณใช้ autoconfig คุณสามารถตรวจสอบฟังก์ชั่นด้วย AC_CHECK_FUNCS () AC_CHECK_FUNCS (pipe sqrt) จะกำหนด HAVE_PIPE และ HAVE_SQRT หากมีฟังก์ชั่นให้ใช้ ฉันไม่รู้ว่ามันเป็นอย่างไรกับเครื่องมือสร้างอื่น ๆ แต่ฉันคิดว่าพวกเขายังสนับสนุนสิ่งนี้ด้วย
quinmars

@MDXF ตั้งแต่ C ++ 17 มี __has_include ฉันไม่คิดว่ามันเป็นมาตรฐานใน C แต่คอมไพเลอร์หลัก (GCC, Clang, ICC, MSVC) ทั้งหมดใช้มันเป็นส่วนขยายเฉพาะผู้ขายแม้ในโหมด C
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 ++ (MSVC) ได้ที่นี่

ฉันคิดว่าคุณกำลังมองหา:

  • _WIN32- กำหนดเป็น 1 เมื่อเป้าหมายการคอมไพล์คือ ARM 32 บิต, ARM 64- บิต, x86 หรือ x64 มิฉะนั้นไม่ได้กำหนด
  • _WIN64- กำหนดเป็น 1 เมื่อเป้าหมายการรวบรวมเป็น ARM 64 บิตหรือ x64 มิฉะนั้นไม่ได้กำหนด

คอมไพเลอร์ gcc สามารถดู MAcros ล่วงหน้าได้ที่นี่

ฉันคิดว่าคุณกำลังมองหา:

  • __GNUC__
  • __GNUC_MINOR__
  • __GNUC_PATCHLEVEL__

ทำ google สำหรับคอมไพเลอร์ที่คุณกำหนดไว้ล่วงหน้า


4

ไม่มีมาโครมาตรฐานที่ตั้งค่าตามมาตรฐาน C คอมไพเลอร์ C บางตัวจะตั้งค่าหนึ่งในบางแพลตฟอร์ม (เช่น GCC patched ของ Apple ตั้งค่าแมโครเพื่อระบุว่ากำลังรวบรวมบนระบบ Apple และสำหรับแพลตฟอร์มดาร์วิน) แพลตฟอร์มและ / หรือคอมไพเลอร์ C ของคุณอาจตั้งค่าบางอย่างเช่นกัน แต่ไม่มีวิธีทั่วไป

เช่นเดียวกับ hayalci กล่าวว่าควรตั้งค่าแมโครเหล่านี้ในกระบวนการสร้างของคุณอย่างใด ง่ายต่อการกำหนดแมโครด้วยคอมไพเลอร์ส่วนใหญ่โดยไม่ต้องแก้ไขโค้ด คุณสามารถส่ง-D MACROต่อไปยัง GCC ได้เช่น

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

4

บน 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/


3
ลิงค์ที่ยอดเยี่ยม ---
MD XF

2

ใช้#define OSsymbolและ#ifdef OSsymbol ตำแหน่งที่ OSsymbol เป็น#defineสัญลักษณ์ 'สามารถระบุระบบปฏิบัติการเป้าหมายของคุณได้

โดยทั่วไปแล้วคุณจะต้องรวมไฟล์ส่วนหัวกลางที่กำหนดสัญลักษณ์ระบบปฏิบัติการที่เลือกและใช้ไดเรกทอรีรวมเฉพาะและไดเรกทอรีห้องสมุดเพื่อรวบรวมและสร้าง

คุณไม่ได้ระบุสภาพแวดล้อมการพัฒนาของคุณ แต่ฉันค่อนข้างมั่นใจว่าคอมไพเลอร์ของคุณมีการกำหนดทั่วโลกสำหรับแพลตฟอร์มทั่วไปและระบบปฏิบัติการ

ดูเพิ่มเติมที่http://en.wikibooks.org/wiki/C_Programming/Preprocessor


2

2

ขออภัยสำหรับการอ้างอิงภายนอก แต่ฉันคิดว่ามันเหมาะกับคำถามของคุณ:

เคล็ดลับ C / C ++: วิธีการตรวจสอบประเภทของระบบปฏิบัติการโดยใช้มาโครที่กำหนดไว้ล่วงหน้าของคอมไพเลอร์


1
โพสต์เมตานั้นถูกลบ ตลกที่เมตาโพสต์ถามเกี่ยวกับโพสต์ที่ถูกลบด้วยเหตุผลของการดูแลถูกลบออกด้วยเหตุผลของการดูแล
MD XF

:) ใช่ บ้าอย่างแน่นอน
bruziuz

2

คุณสามารถใช้ได้ Boost.Predefซึ่งมีมาโครที่กำหนดไว้ล่วงหน้าต่างๆสำหรับแพลตฟอร์มเป้าหมายรวมถึงระบบปฏิบัติการ ( BOOST_OS_*) ใช่เพิ่มมักจะคิดว่าเป็นห้องสมุด C ++ แต่อันนี้เป็นส่วนหัว preprocessor ที่ทำงานกับ 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)
#elif defined(BOOST_OS_AIX)
#elif defined(BOOST_OS_HAIKU)
...
#endif

รายการทั้งหมดสามารถพบได้ในBOOST_OSแมโครระบบปฏิบัติการ


1

ฉันไม่พบคำจำกัดความของไฮกุที่นี่ เพื่อให้สมบูรณ์คำจำกัดความของไหโข่วเป็นเรื่องง่าย__HAIKU__


0

คอมไพเลอร์บางตัวจะสร้าง #defines ที่สามารถช่วยคุณได้ อ่านเอกสารรวบรวมเพื่อกำหนดสิ่งที่พวกเขา MSVCกำหนดหนึ่งที่__WIN32__, GCCมีบางอย่างที่คุณสามารถมองเห็นได้ด้วยtouch foo.h; gcc -dM foo.h


1
gcc: ข้อผิดพลาด: ตัวเลือกบรรทัดคำสั่งที่ไม่รู้จัก '--show-defines' gcc: ข้อผิดพลาดร้ายแรง: ไม่มีการรวบรวมไฟล์อินพุตสิ้นสุดลง
Sebi2020

0

คุณสามารถใช้คำสั่งประมวลผลล่วงหน้าเป็นคำเตือนหรือข้อผิดพลาดเพื่อตรวจสอบเวลารวบรวมที่คุณไม่จำเป็นต้องเรียกใช้โปรแกรมนี้เพียงแค่รวบรวมมัน

#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

ฉันเขียนไลบรารี่ขนาดเล็กเพื่อให้ระบบปฏิบัติการของคุณติดตั้งได้โดยใช้clib (ตัวจัดการแพ็กเกจ C) ดังนั้นจึงเป็นเรื่องง่ายมากที่จะใช้มันเพื่ออ้างอิงสำหรับโปรเจ็กต์ของคุณ

ติดตั้ง

$ clib install abranhe/os.c

การใช้

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

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

ก็จะส่งกลับสตริง ( char*) ที่มีชื่อของระบบปฏิบัติการที่คุณกำลังใช้สำหรับข้อมูลเพิ่มเติมเกี่ยวกับโครงการนี้ตรวจสอบออกเอกสารเกี่ยวกับ Github

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.