Như những người khác đã nói, không có giải pháp chung tốt cho việc này. Loại tên không hiển thị cho bộ tiền xử lý, vì vậy bạn không thể sử dụng #ifdef
để kiểm tra sự tồn tại của chúng.
Tuy nhiên, có một số giải pháp một phần và chúng khác nhau tùy theo nơi yêu cầu cho một loại đã cho.
Có một số phiên bản của tiêu chuẩn ISO C, được ban hành vào năm 1990, 1999 và 2011.Mỗi tiêu chuẩn mới (theo lý thuyết) thay thế và thay thế cái trước đó, và mỗi cái xác định một số loại mới. Ví dụ: tiêu đề tiêu chuẩn C 1999 được thêm vào <stdbool.h>
và <stdint.h>
và các loại bool
, int32_t
, v.v. Nếu bạn muốn sử dụng loại bool
, nhưng vẫn muốn mã của bạn được chuyển sang các triển khai không hỗ trợ C99, bạn có thể làm điều gì đó như:
#if defined(__STDC__) && __STDC_VERSION__ >= 199901L
#include <stdbool.h>
#else
typedef enum { false, true } bool;
#endif
Các enum
loại không cư xử chính xác như C99 tích hợp trong bool
loại, vì vậy bạn cần phải có một chút cẩn thận trong cách bạn sử dụng nó.
Loại uintptr_t
, được xác định trong <stdint.h>
là tùy chọn. Đây là loại không dấu có thể chứa giá trị con trỏ void*
được chuyển đổi mà không mất thông tin; một thực hiện mà không có loại unsigned như vậy (nói, bởi vì con trỏ lớn hơn bất kỳ loại số nguyên) sẽ không cung cấp nó. Bạn không thể kiểm tra trực tiếp cho các loại hình riêng của mình, nhưng bạn có thể kiểm tra các macro mà cung cấp cho giới hạn của nó:
#include <stdint.h>
#ifdef UINTMAX_MAX
/* uintmax_t exists */
#else
/* uintmax_t doesn't exist */
#endif
Bạn có thể cần phải quấn này trong một thử nghiệm cho __STDC__
và __STDC_VERSION__
nếu bạn không thể giả định C99 hoặc tốt hơn.
Loại long long
là loại được xác định trước (không phải là một phần của thư viện), được thêm vào C99. Một lần nữa, bạn không thể kiểm tra trực tiếp, nhưng bạn có thể kiểm tra các macro để xác định giới hạn của nó:
#include <limits.h>
#ifdef LLONG_MAX
/* long long exists */
#else
/* long long *probably* doesn't exist */
#endif
Cuối cùng, có những điều bạn không thể làm trực tiếp trong C, nhưng bạn có thể làm như một phần của quá trình xây dựng chương trình của bạn. Ví dụ, POSIX định nghĩa một loại pid_t
trong tiêu đề POSIX cụ thể <unistd.h>
(đó là loại của một định danh quá trình, được trả về bởi hàm getpid()
). Bạn có thể không có điều kiện bao gồm một tiêu đề - nhưng bạn có thể viết một chương trình nhỏ mà sẽ không biên dịch nếu tiêu đề không tồn tại:
#include <unistd.h>
pid_t dummy;
Là một phần của quá trình xây dựng của bạn, hãy cố gắng biên dịch tập tin này. Nếu thành công, hãy thêm một dòng như
#define HAVE_PID_T
vào tiêu đề cấu hình; nếu nó không thành công, thêm một dòng như
#undef HAVE_PID_T
Trong mã nguồn của bạn, sau đó bạn có thể viết một cái gì đó như:
#include "config.h"
#ifdef HAVE_PID_T
#include <unistd.h>
/* pid_t exists */
#else
/* pid_t doesn't exist */
#endif
GNU Autoconf cung cấp một cách để tự động loại kiểm tra, nhưng nó đã bị chỉ trích vì quá phức tạp và khó sử dụng.
Tất cả điều này giả định rằng, khi bạn đã xác định liệu một loại có tồn tại hay không, bạn có thể làm điều gì đó hữu ích với thông tin đó. Đối với một số loại, như bool
, bạn có thể triển khai phương án thay thế gần tương đương. Đối với pid_t
, mặt khác, có khả năng không phải là một dự phòng tốt, trừ khi bạn chỉ đơn giản là #ifdef
trong tất cả các mã liên quan đến các quy trình. Nếu chương trình của bạn không hoạt động trên hệ thống không có pid_t
và getpid()
, có thể tốt nhất là chỉ viết mã giả định chúng tồn tại. Nếu bạn cố gắng biên dịch mã của bạn trên một hệ thống không cung cấp chúng, nó sẽ ngay lập tức không biên dịch được, và đó có thể là điều tốt nhất bạn có thể làm.
Trong trường hợp cụ thể của bạn. ptrdiff_t nên luôn luôn được xác định nếu bạn bao gồm stddef.h –
Có thể kiểm tra mã cho sự tồn tại và thuộc tính của các định nghĩa cụ thể được gọi là "phản chiếu". Ngôn ngữ kịch bản có xu hướng hỗ trợ phản ánh đầy đủ, một phần vì ngôn ngữ kịch bản tương đối dễ dàng. .NET và sự hỗ trợ JVM cũng được hỗ trợ. Tuy nhiên, đối với ngôn ngữ bản địa, việc hỗ trợ phản chiếu thời gian chạy sẽ đòi hỏi nhiều mã thực thi bổ sung. Một số phản ánh thời gian biên dịch có thể được hỗ trợ mà không có phí trên, nhưng C hầu như không có sự hỗ trợ phản chiếu ngay cả ở thời gian biên dịch. – Steve314
Sử dụng một công cụ như cmake hoặc autotools – szx