Làm cách nào để kiểm tra HĐH bằng chỉ thị tiền xử lý?


194

Tôi cần mã của tôi để làm những việc khác nhau dựa trên hệ điều hành mà nó được biên dịch. Tôi đang tìm kiếm một cái gì đó như thế này:

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

Có cách nào để làm việc này không? Có cách nào tốt hơn để làm điều tương tự?



7
@Cory Klein: Không-không. câu hỏi này đã được hỏi từ nhiều năm trước
John_West

Đây là về CkhôngC++
ilgaar

Câu trả lời:


288

Các Macros được xác định trước cho trang web OS có một danh sách kiểm tra rất đầy đủ. Dưới đây là một vài trong số chúng, với các liên kết đến nơi chúng được tìm thấy:

các cửa sổ

_WIN32   Cả 32 bit và 64 bit
_WIN64   64 bit

Unix (Linux, * BSD, Mac OS X)

Xem câu hỏi liên quan này trên một số cạm bẫy của việc sử dụng kiểm tra này.

unix
__unix
__unix__

Mac OS X

__APPLE__
__MACH__

Cả hai đều được xác định; kiểm tra một trong hai nên làm việc.

Linux

__linux__
linux Lỗi thời (không tuân thủ POSIX)
__linuxLỗi thời (không tuân thủ POSIX)

FreeBSD

__FreeBSD__

Android

__ANDROID__


1
Trang web được cung cấp này không bao gồm iOS, do đó không thể phân biệt giữa iOS và OS X.
Gary Makin

2
Mac OS không định nghĩa __unix__. Tại sao bạn sẽ đưa nó vào danh sách?
Victor Sergienko

1
cpp -dM / dev / null sẽ cung cấp cho bạn một danh sách tất cả các macro gcc được xác định trước trên phiên bản gcc đã cài đặt của bạn
katta

1
Cygwin định nghĩa các unixký hiệu và không xác định các ký hiệu win32, vì vậy hãy cẩn thận. OTOH nó không định nghĩa __CYGWIN__.
David đưa ra

__linux__tương tự như __ANDROID__??
không có ai

72

hiển thị GCC định nghĩa trên Windows:

gcc -dM -E - <NUL:

trên Linux:

gcc -dM -E - </dev/null

Các macro được xác định trước trong MinGW:

WIN32 _WIN32 __WIN32 __WIN32__ __MINGW32__ WINNT __WINNT __WINNT__ _X86_ i386 __i386

trên UNIX:

unix __unix__ __unix

1
Windows và Unices không phải là hệ điều hành duy nhất
phuclv

34

Dựa trên câu trả lời của nadeausoftwareLambda 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
const char *get_platform_name() {
    return (PLATFORM_NAME == NULL) ? "" : PLATFORM_NAME;
}

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

Đã thử nghiệm với GCC và kêu vang:

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

@MD XF thân yêu, vui lòng cho biết các phiên bản Windows, MinGW và Cygwin của bạn
PADYMKO

Windows 7 Enterprise 6.1.7601. Cygwin 2.7.0-1. Tôi không thể tìm thấy phiên bản MinGW nhưng tôi đã tải xuống ngày hôm qua.
MD XF

Có lẽ bạn nên biết rằng - chương trình này là tiêu chuẩn C, vì vậy nó sẽ hoạt động trên tất cả các hệ thống tuân thủ.
MD XF

thân yêu @MD XF, cảm ơn bạn về thông tin này. Tôi đã thêm bạn là người đóng góp trên đầu câu trả lời này.
PADYMKO

10

Trong hầu hết các trường hợp, tốt hơn là kiểm tra xem một chức năng nhất định có mặt hay không. Ví dụ: nếu hàm pipe()tồn tại hay không.


3
Có một cách dễ dàng để kiểm tra nếu một chức năng được xác định?
hayalci

1
Nếu bạn đang sử dụng autoconfig, bạn có thể kiểm tra các chức năng với AC_CHECK_FUNCS (). AC_CHECK_FUNCS (sqrt ống) sẽ xác định Lawr_PIPE và Lawr_SQRT nếu các chức năng có sẵn. Tôi không biết nó như thế nào với các công cụ xây dựng khác, nhưng tôi đoán họ cũng hỗ trợ điều này theo một cách nào đó.
quinmars

@MDXF Kể từ C ++ 17, có __has_include. Tôi không nghĩ rằng nó đã được chuẩn hóa trong C, nhưng tất cả các trình biên dịch chính (GCC, Clang, ICC, MSVC) đều triển khai nó như một phần mở rộng dành riêng cho nhà cung cấp, ngay cả trong chế độ 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

Trình biên dịch Microsoft C / C ++ (MSVC) Các macro được xác định trước có thể được tìm thấy ở đây

Tôi nghĩ rằng bạn đang tìm kiếm:

  • _WIN32- Được xác định là 1 khi mục tiêu biên dịch là ARM 32 bit, ARM 64 bit, x86 hoặc x64. Mặt khác, không xác định
  • _WIN64- Được xác định là 1 khi mục tiêu biên dịch là ARM 64-bit hoặc x64. Nếu không, không xác định.

Trình biên dịch gcc MAcros PreDefined có thể được tìm thấy ở đây

Tôi nghĩ rằng bạn đang tìm kiếm:

  • __GNUC__
  • __GNUC_MINOR__
  • __GNUC_PATCHLEVEL__

Làm một google cho trình biên dịch thích hợp của bạn được xác định trước.


4

Không có macro tiêu chuẩn nào được đặt theo tiêu chuẩn C. Một số trình biên dịch C sẽ đặt một trên một số nền tảng (ví dụ GCC được vá của Apple đặt một macro để chỉ ra rằng nó đang biên dịch trên hệ thống Apple và cho nền tảng Darwin). Nền tảng của bạn và / hoặc trình biên dịch C của bạn cũng có thể thiết lập một cái gì đó, nhưng không có cách nào chung.

Giống như hayalci đã nói, tốt nhất là nên cài đặt các macro này trong quá trình xây dựng của bạn. Thật dễ dàng để xác định một macro với hầu hết các trình biên dịch mà không cần sửa đổi mã. Bạn chỉ có thể chuyển qua -D MACROGCC, tức là

gcc -D Windows
gcc -D UNIX

Và trong mã của bạn:

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

4

Trên MinGW, _WIN32kiểm tra xác định không hoạt động. Đây là một giải pháp:

#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

Để biết thêm thông tin xin vui lòng xem: https://sourceforge.net/p/predef/wiki/OperatingSystems/


3
Liên kết tuyệt vời. ---
MD XF

2

Sử dụng #define OSsymbol#ifdef OSsymbol trong đó OSsymbol là #definebiểu tượng 'có thể xác định HĐH đích của bạn.

Thông thường, bạn sẽ bao gồm một tệp tiêu đề trung tâm xác định biểu tượng HĐH đã chọn và sử dụng các thư mục bao gồm và thư mục dành riêng cho hệ điều hành để biên dịch và xây dựng.

Bạn đã không chỉ định môi trường phát triển của mình, nhưng tôi khá chắc chắn trình biên dịch của bạn cung cấp định nghĩa toàn cầu cho các nền tảng và hệ điều hành phổ biến.

Xem thêm http://en.wikibooks.org/wiki/C_Programming/Pre Processor


2

2

Xin lỗi vì đã tham khảo bên ngoài, nhưng tôi nghĩ nó phù hợp với câu hỏi của bạn:

Mẹo C / C ++: Cách phát hiện loại hệ điều hành bằng cách sử dụng macro trình biên dịch được xác định trước


1
Bài viết meta đó đã bị xóa. Thật buồn cười là một bài đăng meta hỏi về bài viết bị xóa vì lý do kiểm duyệt đã bị xóa vì lý do kiểm duyệt.
MD XF

:) Vâng. Hoàn toàn điên rồ
bruziuz

2

Bạn có thể sử dụng Boost.Predefcó chứa các macro được xác định trước khác nhau cho nền tảng đích bao gồm cả OS ( BOOST_OS_*). Có boost thường được coi là một thư viện C ++, nhưng cái này là một tiêu đề tiền xử lý cũng hoạt động với C!

Thư viện này định nghĩa một tập hợp trình biên dịch, kiến ​​trúc, hệ điều hành, thư viện và các số phiên bản khác từ thông tin mà nó có thể thu thập của C, C ++, Objective C và Objective C ++ được xác định trước trong các tiêu đề có sẵn nói chung. Ý tưởng cho thư viện này nảy sinh từ một đề xuất mở rộng thư viện Boost Config để cung cấp nhiều thông tin và nhất quán hơn các định nghĩa tính năng mà nó hỗ trợ. Những gì tiếp theo là một phiên bản chỉnh sửa của đề xuất ngắn gọn đó.

Ví dụ

#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

Danh sách đầy đủ có thể được tìm thấy trong các BOOST_OSmacro hệ điều hành


1

Tôi không tìm thấy định nghĩa Haiku ở đây. Để được hoàn thành, định nghĩa Haiku-os rất đơn giản__HAIKU__


0

Một số trình biên dịch sẽ tạo ra #defines có thể giúp bạn điều này. Đọc tài liệu biên dịch để xác định chúng là gì. MSVC định nghĩa một điều đó __WIN32__, GCC có một số bạn có thể thấy vớitouch foo.h; gcc -dM foo.h


1
gcc: error: tùy chọn dòng lệnh không được nhận dạng '--show-định nghĩa' gcc: lỗi nghiêm trọng: không có quá trình biên dịch tệp đầu vào bị chấm dứt.
Sebi2020

0

Bạn có thể sử dụng các chỉ thị tiền xử lý như cảnh báo hoặc lỗi để kiểm tra tại thời điểm biên dịch mà bạn không cần phải chạy chương trình này mà chỉ cần biên dịch nó.

#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

Tôi đã viết một thư viện nhỏ để tải hệ điều hành mà bạn đang sử dụng, nó có thể được cài đặt bằng clib (Trình quản lý gói C), vì vậy thật đơn giản để sử dụng nó làm phụ thuộc cho các dự án của bạn.

Tải về

$ clib install abranhe/os.c

Sử dụng

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

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

Nó trả về một chuỗi ( char*) với tên của hệ điều hành bạn đang sử dụng, để biết thêm thông tin về dự án này, hãy kiểm tra tài liệu trên Github .

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.