2012-09-24 14 views
8

Nếu trình biên dịch có loại nhất định (ví dụ: ptrdiff_t) dưới dạng loại được nhúng, tôi không muốn gõ lại nó. Tôi biết rằng mã dưới đây không hoạt động đúng cách mà tôi mong đợi.Làm thế nào tôi có thể kiểm tra một loại nhất định đã được xác định trong trình biên dịch C?

#ifndef ptrdiff_t 
    typedef long int ptrdiff_t; 
#endif 

Làm thế nào tôi có thể kiểm tra một loại nhất định đã được xác định trong C biên dịch?

+1

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 –

+2

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

+0

Sử dụng một công cụ như cmake hoặc autotools – szx

Trả lời

1

Trong câu hỏi của bạn, bạn là một chút bối rối 2 thứ khác nhau:

Việc xây dựng trong các loại, giống như int, float, vv Đây là những loại stnd và chúng được định nghĩa là tất cả các trình biên dịch. Các loại như __int64 không phải là tiêu chuẩn, nhưng chúng được định nghĩa trong một số trình biên dịch. Bạn không cần phải làm gì để sử dụng chúng. Đồng thời bạn không thể tìm ra trong mã của bạn nếu chúng được xác định hay không. Điều này có thể được tìm ra chỉ từ các tài liệu trên trình biên dịch. Bạn có thể viết:

#ifdef MSVC 
     .... Microsoft specific code 
#else 
     .... Code for other compiler. 
#endif 

Cách tiếp cận này cho phép bạn tạo loại compiler independent environment.

Ngoài các loại được tạo sẵn, có các loại đến từ tiêu đề. Một số tiêu đề có cấu trúc như:

#ifndef ptrdiff_t_DEFINED 
    #define ptrdiff_t_DEFINED 
    typedef long int ptrdiff_t; 
#endif 

Lưu ý rằng bộ phận xử lý macroprocessor vẫn nằm ngoài giới hạn của loại. Bạn không thể kiểm tra xem loại được xác định hay không, nhưng bạn có thể dễ dàng kiểm tra xem định nghĩa đã được xác định chưa.

Tiêu đề nào được bao gồm trong mã của bạn mà bạn tự thực hiện. Điều này có nghĩa là các định nghĩa này không phải là in the compiler itself. Chúng nằm trong tập hợp các định nghĩa của đơn vị dịch hiện tại. Đối với trình biên dịch, chúng có sự khác biệt nhỏ so với các định nghĩa kiểu khác mà bạn viết trong mã của riêng bạn.

Một số trình biên dịch hoặc tiêu đề hệ thống không có "bảo vệ defns" như trong ví dụ trên. Trong trường hợp này, điều duy nhất bạn có thể làm là theo dõi những tiêu đề đang đến và bao gồm/không bao gồm các tiêu đề này, bằng cách sử dụng các bảo vệ #ifdef của riêng bạn xung quanh các câu lệnh #include.

5

Không có cách nào để làm điều đó nói chung. Trong một số trường hợp, có thể có macro được xác định cùng lúc với loại mà bạn có thể sử dụng.

Trong ví dụ cụ thể của bạn, bạn có thể #include <stddef.h>, phải luôn định nghĩa ptrdiff_t.

0

Do việc xác định lại cấu trúc dành riêng cho ngôn ngữ C thường dẫn đến lỗi thời gian biên dịch nên không thể kiểm tra nó nói chung. Nếu bạn quan tâm (đối với quá trình học tập/học tập), bạn có thể viết một trình biên dịch cơ bản để kiểm tra các ngoại lệ/lỗi trên chương trình C của bạn để phát hiện xem một loại có được bảo lưu hay không.

4

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><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____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_tgetpid(), 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.

Các vấn đề liên quan