2009-03-07 12 views
19

Mam plik header port.h, port.c, a mój main.cniezdefiniowany C struct naprzód deklaracja

pojawia się następujący błąd: Używa 'porty' niezdefiniowane struct 'port_t'

I Myślałem, że zadeklarowałem strukturę w moim pliku .h i posiadanie właściwej struktury w pliku .c było w porządku.

Muszę mieć deklarację przekazania, ponieważ chcę ukryć niektóre dane w pliku port.c.

W moim port.h Mam następujący:

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

Wielkie dzięki za wszelkie sugestie,

+0

kompilator gcc C99 – ant2009

+9

Należy pamiętać, że nazwy portów jedna postać nie będą bardzo ekscytujące! –

Odpowiedz

24

Niestety, kompilator potrzebuje aby poznać rozmiar port_t (w bajtach) podczas kompilowania pliku main.c, więc potrzebna jest pełna definicja typu w pliku nagłówkowym.

+0

widocznie masz rację. Wydaje się, że C obsługuje to inaczej niż C++. –

+5

@litb: co masz na myśli? Wierzę w C++, main.cpp nadal potrzebowałby pełnej definicji port_t w celu utworzenia instancji "ports". –

+1

@Matthew: warto wyjaśnić, że jest to pełna definicja _type, która musi znajdować się w pliku nagłówkowym; definicja zmiennej przechodzi do pliku źródłowego. –

15

Jeśli chcesz ukryć wewnętrzne dane struktury port_t, możesz użyć techniki, takiej jak biblioteka standardowa obsługująca obiekty FILE. Kod klienta zajmuje się tylko pozycjami FILE*, więc nie potrzebują (a nawet generalnie nie mogą) mieć żadnej wiedzy na temat tego, co faktycznie znajduje się w strukturze FILE. Wadą tej metody jest to, że kod klienta nie może po prostu zadeklarować, że zmienna jest tego typu - mogą mieć tylko wskaźniki do niej, więc obiekt musi zostać utworzony i zniszczony za pomocą niektórych interfejsów API i dla wszystkich zastosowań obiekt musi być przez niektóre API.

Zaletą tego jest to, że masz ładny, czysty interfejs do tego, w jaki sposób należy używać obiektów port_t, i pozwalasz zachować prywatne rzeczy prywatne (nieprywatne rzeczy potrzebują funkcji getter/setter, aby klient mógł uzyskać do nich dostęp).

Podobnie jak sposób obsługi plików I/O w bibliotece C.

+0

Nawet struktura FILE jest wyraźnie ułożona w stdio.h. Przynajmniej w moim systemie. "typedef struct __sFILE {...} FILE;" Za pomocą wskaźników FILE nigdy nie musimy widzieć ich elementów wewnętrznych (które są bardzo interesujące - wskaźniki funkcji do odczytu/zapisu/itd.), Ale one SĄ nadal tam obecne. –

+0

Uwaga: Aby poradzić sobie ze wskaźnikami FILE *, a nie z plikami typu struct FILE *, musisz użyć wersji "typedef". Powyższy kod wymaga "struct port_t". Jeśli byłby to "typedef struct port_t {...} PORT", mógłby użyć wskaźnika PORT * podobnego do wskaźnika FILE *. –

+0

@Chris, nie musi być zadeklarowany w pełni, implementacja mogłaby technicznie zdefiniować strukturę PLIKA jako char [X], ponieważ nie ma w standardzie nic, co by narzucało strukturę - więc można by ją ukryć. – paxdiablo

0

polecam inny sposób:

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

to na ogół nie jest dobre zdefiniowanie zmiennych w pliku nagłówka.

+1

nie definiował zmiennej w nagłówku, próbował przekazać dalej deklarację typu port_t. –

+0

Dlaczego nie używa funkcji get/set lub simulair mnie bije ... Ale masz rację ... Po prostu dawałem sugestię ... – eaanon01

6

Typowym rozwiązaniem, które używam:

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

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

użyć port_p w interfejsach funkcyjnych. Trzeba będzie utworzyć specjalną malloc (i za darmo) owijarki w port.h także:

port_p portAlloc(/*perhaps some initialisation args */); 
portFree(port_p);