2014-12-21 15 views
28

Tôi đã nhìn vào một số macro tiền xử lý được sử dụng trong OpenSSL, và tôi tình cờ gặp sau đây từ crypto/stack/safestack.h:Toán tử điều kiện có giá trị hằng số (đúng)?

#define CHECKED_STACK_OF(type, p) \ 
    ((_STACK*) (1 ? p : (STACK_OF(type)*)0)) 

#define CHECKED_SK_FREE_FUNC(type, p) \ 
    ((void (*)(void *)) ((1 ? p : (void (*)(type *))0))) 

#define CHECKED_SK_FREE_FUNC2(type, p) \ 
    ((void (*)(void *)) ((1 ? p : (void (*)(type))0))) 

Tôi đoán bằng văn bản theo cách đó để làm việc xung quanh một lỗi biên dịch (có thể là một cái gì đó cổ hasn đã được nhà cung cấp hỗ trợ trong hơn một thập kỷ).

Mục đích sử dụng số 1 ở trên là gì vì nó luôn đúng?

+3

Xác minh loại 'p', có thể - toán hạng thứ hai và thứ ba của toán tử điều kiện phải được chuyển đổi thành cùng loại. –

Trả lời

25

Mã của nó kiểm tra kỹ nếu loại chính xác được chuyển. Con trỏ p được truyền và dọc theo kiểu con trỏ đó cũng phải được nhập bằng tay trong macro.

Biểu thức bậc ba sẽ luôn trả về toán hạng thứ hai nhưng cả toán hạng thứ hai và thứ ba sẽ được kiểm tra nếu kiểu của chúng khớp nhau và nếu không, bạn sẽ gặp lỗi trình biên dịch.

Một ví dụ đơn giản:

int* p = NULL ; 

1 ? p : (float*)p ; //error 

1 ? p : (int*)p ;  //ok 
+0

Cảm ơn bạn rất nhiều. – jww

13

Đó là một sự khẳng định tĩnh về loại chức năng trước khi các diễn viên, cung cấp một kiểu an đúc.

Từ C11 (n1570) 6.5.15 (từ phần hạn chế)

nhà điều hành có điều kiện

(3) Một trong những điều sau đây sẽ tổ chức cho các toán hạng thứ hai và thứ ba:

  • [bỏ qua công cụ không trỏ chuột]
  • cả hai toán hạng là con trỏ đến phiên bản đủ điều kiện hoặc không đủ tiêu chuẩn của comp các loại có thể ăn được;
  • một toán hạng là một con trỏ và một là hằng số con trỏ null; hoặc
  • một toán hạng là một con trỏ trỏ đến loại đối tượng và loại kia là con trỏ đến phiên bản đủ điều kiện hoặc không đủ tiêu chuẩn của void.

Các toán hạng thứ ba là một con trỏ tới một hàm (để viên đạn cuối cùng không bao giờ áp dụng), vì vậy đây biên dịch (không có cảnh báo) chỉ nếu một trong hai p là một con trỏ null không đổi hoặc của một loại tương thích với void (*)(type) cho macro cuối cùng (sau khi chuyển đổi sang một con trỏ hàm, nếu p là một hàm thiết kế).

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