2009-03-07 34 views
19

Tôi có một tập tin tiêu đề port.h, port.c, và main.c tôiC struct không xác định phía trước khai

tôi nhận được lỗi sau: sử dụng 'cổng' undefined struct 'port_t'

tôi suy nghĩ như tôi đã tuyên bố cấu trúc trong tập tin .h của tôi và có cấu trúc thực tế trong tập tin .c là ok.

Tôi cần có tuyên bố chuyển tiếp vì tôi muốn ẩn một số dữ liệu trong tệp port.c của mình.

Trong port.h của tôi, tôi đã điều sau đây:

/* port.h */ 
struct port_t; 

port.c:

/* port.c */ 
#include "port.h" 
struct port_t 
{ 
    unsigned int port_id; 
    char name; 
}; 

main.c:

/* main.c */ 
#include <stdio.h> 
#include "port.h" 

int main(void) 
{ 
struct port_t ports; 

return 0; 
} 

Rất cám ơn cho bất cứ đề nghị,

+0

trình biên dịch gcc C99 – ant2009

+9

Lưu ý rằng tên cổng một ký tự không sẽ rất thú vị! –

Trả lời

24

Thật không may, trình biên dịch cần để biết kích thước của port_t (tính bằng byte) trong khi biên dịch main.c, vì vậy bạn cần định nghĩa kiểu đầy đủ trong tệp tiêu đề.

+0

dường như bạn đã đúng. C dường như xử lý điều này khá khác với C++. –

+5

@ litb: ý của bạn là gì? Tôi tin rằng trong c + +, main.cpp vẫn sẽ cần một định nghĩa đầy đủ của port_t để tạo ra các "cổng" dụ. –

+1

@Matthew: có thể đáng làm rõ rằng đó là toàn bộ _type_ defintion cần phải có trong tệp tiêu đề; định nghĩa biến đi trong tệp nguồn. –

15

Nếu bạn muốn ẩn dữ liệu nội bộ của cấu trúc port_t, bạn có thể sử dụng kỹ thuật như cách thư viện chuẩn xử lý đối tượng FILE. Mã khách hàng chỉ giao dịch với FILE* mục, vì vậy họ không cần (thực sự, thường thì không thể) có bất kỳ kiến ​​thức nào về những gì thực sự trong cấu trúc FILE. Hạn chế của phương thức này là mã khách hàng không thể khai báo một biến đơn giản là kiểu đó - chúng chỉ có thể có con trỏ đến nó, vì vậy đối tượng cần được tạo và hủy sử dụng một số API, và tất cả sử dụng đối tượng phải thông qua một số API.

Lợi thế của việc này là bạn có giao diện sạch đẹp để sử dụng các đối tượng port_t và cho phép bạn giữ riêng tư mọi thứ (những thứ không riêng tư cần chức năng getter/setter để khách hàng truy cập chúng).

Cũng giống như cách FILE I/O được xử lý trong thư viện C.

+0

Ngay cả cấu trúc FILE được trình bày rõ ràng trong stdio.h. Ít nhất, trên hệ thống của tôi. "typedef struct __sFILE {...} TẬP_TIN"; Thông qua con trỏ FILE chúng ta không bao giờ cần phải nhìn thấy nội bộ của họ (đó là rất thú vị - con trỏ chức năng để làm thế nào để đọc/ghi/vv) nhưng họ vẫn còn đó. –

+0

Cũng lưu ý: Để xử lý con trỏ FILE * và không phải con trỏ FILE * struct, bạn cần sử dụng phiên bản "typedef". Đoạn mã trên yêu cầu "struct port_t". Nếu nó là "typedef struct port_t {...} PORT" thì nó có thể sử dụng một con trỏ PORT * tương tự như con trỏ FILE *. –

+0

@ Chris, nó không phải được khai báo đầy đủ, việc triển khai có thể xác định một cấu trúc FILE như char [X] vì không có gì trong tiêu chuẩn quy định cấu trúc chứa gì - vì vậy nó có thể bị ẩn. – paxdiablo

0

Tôi muốn giới thiệu một cách khác nhau:

/* port.h */ 
#ifndef _PORT_H 
#define _PORT_H 
typedef struct /* Define the struct in the header */ 
{ 
    unsigned int port_id; 
    char name; 
}port_t; 
void store_port_t(port_t);/*Prototype*/ 
#endif 

/* port.c */ 
#include "port.h" 
static port_t my_hidden_port; /* Here you can hide whatever you want */ 
void store_port_t(port_t hide_this) 
{ 
    my_hidden_port = hide_this; 
} 

/* main.c */ 
#include <stdio.h> 
#include "port.h" 
int main(void) 
{ 
    struct port_t ports; 
    /* Hide the data with next function*/ 
    store_port_t(ports); 
    return 0; 
} 

Nó nói chung là không tốt để xác định các biến trong một tập tin tiêu đề.

+1

anh ta không định nghĩa một biến trong một tiêu đề, anh ta đang cố gắng chuyển tiếp khai báo kiểu port_t. –

+0

Tại sao anh ta không sử dụng chức năng get/set hoặc simulair đánh bại tôi ... Nhưng yea bạn chính xác ... Tôi chỉ đưa ra gợi ý ... – eaanon01

6

Một giải pháp phổ biến mà tôi sử dụng:

/* port.h */ 
typedef struct port_t *port_p; 

/* port.c */ 
#include "port.h" 
struct port_t 
{ 
    unsigned int port_id; 
    char name; 
}; 

Bạn sử dụng port_p trong giao diện chức năng. Bạn sẽ cần phải tạo malloc đặc biệt (và miễn phí) wrappers trong port.h cũng như:

port_p portAlloc(/*perhaps some initialisation args */); 
portFree(port_p); 
Các vấn đề liên quan