2011-02-07 40 views
5

Trong Objective-C id là một typedef:Mục tiêu-C; typedef objc_object thay thế cho id không có con trỏ;

typedef struct objc_object { 
    Class isa; 
} *id; 

Vì vậy, tôi có thể tuyên bố (và khởi tạo) một ví dụ biến như thế này:

// using id 
id po_one = @"one"; 

Biên dịch tốt.

Kể từ khi tôi đặt tên cho loại của tôi trong một chương trình riêng và kể từ khi tôi không thích con trỏ ngụ ý trong id typedef Tôi muốn thêm một typedef riêng (với O cho đối tượng) như thế này:

typedef struct objc_object O; 

Vì vậy, một biến khai (với khởi tạo) có thể trông giống như:

// using O 
O * po_two = @"two"; 

này biên dịch với một cảnh báo:

khởi tạo từ i ncompatible con trỏ loại

Theo như tôi hiểu typedefs Tôi nghĩ rằng sau này sẽ tương đương với:

// using struct objc_object 
struct objc_object * po_three = @"three"; 

nào một lần nữa biên dịch tốt.

Đó là đáng ngạc nhiên rằng:

po_two = po_one; 
po_two = po_three; 

cả biên dịch mà không cần cảnh báo.

Vì vậy, tôi đã cố gắng:

typedef struct objc_object * PO; 

để xem liệu nó hoạt động mà không báo trước nếu tôi bao gồm con trỏ (là chính xác những điều tôi muốn tránh - vì vậy chỉ vì lý do kiểm tra) để xem liệu một typedef ngoài định nghĩa cấu trúc hoạt động khác với typedef trong định nghĩa cấu trúc (là định nghĩa của id trong trường hợp này).

// using PO 
PO po_four = @"four"; 

Điều đó cũng hoạt động tốt.

Nếu tôi sử dụng:

#define O struct objc_object 

dạng một công trình sử dụng O lần nữa biên dịch mà không báo trước.

Nhưng tôi thích sử dụng typedef thay vì xác định bất cứ khi nào có thể.

Tôi đang bối rối. Sự hiểu lầm của tôi với typedefs là gì?

+0

Trình biên dịch nào? – JeremyP

+1

Ngoài ra, bạn có thể sử dụng 'NSObject *' thay vì 'O *', ví dụ: 'NSObject * po_two = @" hai ";', trong hầu hết các trường hợp. –

Trả lời

2

Tôi không phải là chuyên gia về trình biên dịch, vì vậy có lẽ một chuyên gia thực sự có thể cung cấp cho bạn câu trả lời tốt hơn. Trong mọi trường hợp, dựa trên kiến ​​thức của tôi, khi trình biên dịch kiểm tra kiểu, nó căn cứ kiểm tra này trên "cây phân tích", tạo ra một loại bảng cho tất cả các cấu trúc kiểu dữ liệu có thể, và kiểm tra xem hai định nghĩa có trỏ đến cùng hàng không trong bảng. Vì vậy, nó hoạt động bằng cách lấy các biểu tượng và định nghĩa kiểu từ bảng này và so sánh chúng. Bây giờ "struct objc_object" là một trong những cấu trúc dữ liệu này.Sau đó, khi id được xác định, nó tạo ra một mục khác: "id -> struct objc_object *". Định nghĩa po_three dẫn đến cùng một tham chiếu: "struct objc_object *" (infact "=" có mức ưu tiên thấp nhất). Điều tương tự cũng xảy ra với po_four, bởi vì PO dẫn theo định nghĩa đến cùng một tham chiếu, một lần nữa (PO -> struct objc_object *). Khi bạn sử dụng định nghĩa với #define, nhờ tiền xử lý bạn vẫn đang tham chiếu đến "struct objc_object *". Nhưng khi bạn sử dụng

O * po_two = @"two"
, bạn đang thực sự cố gắng khớp một loại là "id" (@ "two"), đó là "struct objc_object *" và một số khác là con trỏ tới "struct objc_object" nhưng ngay cả khi một cách hợp lý chúng giống nhau, chúng không dẫn đến cùng một tham chiếu trong bảng. Lý do là vì "O" loại đã được xác định được nêu ra, do đó, po_two chỉ đơn giản là được lưu trữ trong bảng biểu tượng như một con trỏ đến "O" và "O -> struct objc_object". Và đó là lý do của cảnh báo: po_two là một con trỏ đến một cái gì đó khác với @ "hai".

Tôi có một sự tò mò: bạn đã cố gắng vẽ biểu đồ bảng bằng cách sử dụng "nm" chưa?

+0

Có thể là một dự đoán tốt với các mục bảng không khớp. Tôi đã thử nm nhưng không cung cấp thông tin hữu ích. Trình gỡ lỗi cũng chỉ hiển thị các loại giống nhau - ít nhất là sau khi khởi tạo. Dự đoán nhỏ của tôi vào lúc này là có một bản hack được tích hợp vào gcc cho phép bất kỳ con trỏ nào được đúc thành id. Nhưng có lẽ họ chỉ đơn giản là quên để xem xét các quy tắc loại c bình thường (mà nên dẫn đến các loại tương đương cho id và O *) và do đó typedef mang lại cảnh báo. – carpetemporem

+0

Có, và điều này có thể giải thích cảnh báo thiếu trong po_two = po_three. – viggio24

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