2012-02-15 34 views
8

Tôi không phải là chuyên gia về ngôn ngữ lập trình hướng đối tượng cấp thấp hơn và tôi đang viết một số mã C cho một dự án tại nơi làm việc. Tôi đang cố gắng tạo ra một số kiểu dữ liệu trừu tượng tốt để làm việc cùng, và Googling xung quanh khiến tôi nhận ra rằng mọi người sử dụng ADT dựa trên cấu trúc theo hai cách. Một số người xác định loại dữ liệu dưới dạng cấu trúc:Khi nào tôi nên gõ struct so với con trỏ để cấu trúc?

typedef struct adt { 
    //content here 
} adt; 

và hiển thị nó với thế giới trong tệp tiêu đề.

Khác định nghĩa một kiểu dữ liệu như một con trỏ để struct:

// In .c file: 
typedef struct adt_s { 
    //content here 
} adt_s, *adt; 


// In .h file: 
typedef struct adt_s *adt; 

Tôi hiểu rằng phương pháp này cho phép bạn typedef một cấu trúc mà không cho thế giới bên ngoài bất kỳ kiến ​​thức về những gì bên trong struct này, do đó các lập trình viên chỉ có thể các chức năng sử dụng được cung cấp trong cùng một tệp tiêu đề để hoạt động trên loại dữ liệu này.

Có một lý do nào khác để chọn cách khác không? Có một quy tắc chung "chung" cho khi xác định ADT là cấu trúc và khi nào chúng ta định nghĩa chúng như là con trỏ tới cấu trúc?

Trả lời

6

Bạn có thể chuyển tiếp khai báo một struct mà không typedef quá - sự phân biệt duy nhất là:

  • dù giao diện trông sạch có hoặc không có từ khóa struct
  • dù giao diện trông sạch có hoặc không có con trỏ rõ ràng *

Ví dụ:

struct S1; 
typedef struct S2 S2; 
typedef struct S3_s *S3; 

void foo1(struct S1 *arg); 
void foo2(S2 *arg); 
void foo3(S3); 

Rõ ràng điều này chỉ áp dụng cho cấu trúc được khai báo chuyển tiếp trong tiêu đề giao diện.

Nếu bạn không ẩn triển khai cấu trúc ngay từ đầu, hãy chọn giữa S1S2 là vấn đề ưu tiên (hoặc nhất quán). Tôi sẽ không sử dụng S3 trừ khi nó là một loại thực sự mờ đục/ẩn.

Tùy chọn cá nhân sẽ sử dụng S1 (từ khóa cấu trúc rõ ràng) cho các tập hợp lớn/phức tạp và S2 cho các cấu trúc nhỏ bạn có thể coi như giá trị và không phải lúc nào cũng đi qua con trỏ. YMMV.

+0

Đối với mục đích dễ đọc có lẽ nó tốt hơn để viết 'typedef struct S3_s * S3' thay vì 'typedef struct S3_s * S3', không có? – Eregrith

+0

@Eregrith: nếu bạn đi theo ngữ nghĩa ngôn ngữ chính thức, 'typedef struct S3_s * S3' nói rằng người khai báo' * S3' có kiểu 'struct S3_s' và lớp lưu trữ' typedef', vì vậy hãy đặt dấu hoa thị với định danh thực sự là thành ngữ ; tuy nhiên, việc đặt dấu hoa thị với kiểu là phù hợp hơn với bao nhiêu (nhiều nhất?) mọi người nghĩ về các khai báo; theo như tôi đồng ý, cả hai phiên bản đều miễn là bạn nhất quán ... – Christoph

+0

Tôi chỉ chọn khoảng cách đó cho tính nhất quán với OP, vì tôi có thể thấy lợi ích theo cách này. – Useless

1

Quyết định ẩn hoặc không ẩn hoàn toàn với bạn với tư cách là nhà thiết kế thư viện của bạn. Nếu bạn muốn giữ quyền thay đổi struct theo ý muốn trong tương lai, bạn không được để lộ bất kỳ thành viên nào của nó cho "thế giới". Nếu bạn đang cung cấp struct làm phương tiện để liên lạc với thư viện của mình ngay từ đầu (ví dụ: struct đại diện cho một điểm bằng 3D), thì bạn không thể ẩn thành viên khỏi thế giới, vì nó sẽ đánh bại mục đích.

1

đọc Linus Torvalds post Chương 5: Typedefs

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