2009-03-07 2 views
19

У меня есть файл заголовка port.h, port.c, и моя main.cнеопределенными C структура опережающее объявление

Я получаю следующее сообщение об ошибке: использует '-портов не определен структура 'port_t'

I думал, как я объявил структуру в моем .h-файле и имея фактическую структуру в файле .c, было в порядке.

Мне нужно иметь переднее объявление, поскольку я хочу скрыть некоторые данные в файле port.c.

В моей port.h я следующее:

/* 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; 
} 

Большое спасибо за любые предложения,

+0

компилятор GCC C99 – ant2009

+9

Обратите внимание, что имена портов в один символ не будет очень интересно! –

ответ

24

К сожалению, необходим компилятор знать размер port_t (в байтах) при компиляции main.c, поэтому вам нужно полное определение типа в файле заголовка.

+0

очевидно, что вы правы. C, похоже, справляется с этим совсем иначе, чем C++. –

+5

@litb: что вы имеете в виду? Я верю в C++, main.cpp все равно потребуется полное определение port_t, чтобы создать экземпляр «ports». –

+1

@Matthew: возможно, стоит уточнить, что это полная _type_ defintion, которая должна быть в файле заголовка; определение переменной идет в исходном файле. –

15

Если вы хотите скрыть внутренние данные структуры port_t, вы можете использовать технику, например, как стандартная библиотека обрабатывает объекты FILE. Клиентский код обрабатывает только FILE* элементов, поэтому им не нужно (в действительности, как правило, не может) иметь какие-либо знания о том, что на самом деле находится в структуре FILE. Недостатком этого метода является то, что клиентский код не может просто объявить переменную такого типа - у них могут быть только указатели на нее, поэтому объект должен быть создан и уничтожен с использованием некоторого API, и все использует объект должен быть через некоторый API.

Преимущество этого в том, что у вас есть чистый чистый интерфейс для того, как должны использоваться объекты port_t, и позволяет вам хранить личные вещи в закрытом режиме (для частных лиц нужны функции getter/setter для доступа к ним).

Точно так же, как FILE I/O обрабатывается в библиотеке C.

+0

Даже структура FILE четко выложена в stdio.h. По крайней мере, в моей системе. "typedef struct __sFILE {...} FILE;" С помощью указателей FILE нам не нужно видеть их внутренности (которые очень интересны - указатели на функции для чтения/записи и т. Д.), Но они все еще существуют. –

+0

Также обратите внимание: чтобы иметь дело с указателями FILE *, а не с указателями FILE *, вам нужно использовать версию «typedef». Вышеприведенный код требует «struct port_t». Если это «typedef struct port_t {...} PORT», тогда он может использовать указатель PORT *, похожий на указатели FILE *. –

+0

@Chris, он не должен быть объявлен полностью, реализация может технически определить структуру FILE как char [X], поскольку в стандарте нет ничего, что диктует то, что содержит эта структура, поэтому оно может быть скрыто. – paxdiablo

0

Я рекомендовал бы по-другому:

/* 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; 
} 

Это обычно не хорошо для определения переменных в файле заголовка.

+1

он не определял переменную в заголовке, он пытался переслать объявление типа port_t. –

+0

Почему он не использует функции get/set или simulair, меня бьет ... Но да, вы правы ... Я просто давал предложение ... – eaanon01

6

Общее решение, которое я использую:

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

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

Вы используете port_p в функциональных интерфейсов. Вам нужно будет создать специальный таНос (и бесплатно) упаковщики в port.h, а также:

port_p portAlloc(/*perhaps some initialisation args */); 
portFree(port_p); 
Смежные вопросы