2009-03-07 14 views
19

Tengo un archivo de cabecera port.h, port.c, y mi main.cindefinido C struct declaración adelantada

me sale el siguiente error: usos 'puertos' no definido struct 'port_t'

I pensado como he declarado la estructura en mi archivo .h y tener la estructura real en el archivo .c estaba bien.

Necesito tener la declaración directa ya que quiero ocultar algunos datos en mi archivo port.c.

En mi port.h Tengo el siguiente:

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

Muchas gracias por todas las sugerencias,

+0

compilador gcc C99 – ant2009

+9

Tenga en cuenta que los nombres de puerto de un solo carácter no van a ser muy emocionante! –

Respuesta

24

Desafortunadamente, el compilador necesita para saber el tamaño de port_t (en bytes) al compilar main.c, por lo que necesita la definición de tipo completo en el archivo de encabezado.

+0

Aparentemente tienes razón. C parece manejar esto de manera bastante diferente que C++. –

+5

@litb: ¿qué quieres decir? Creo en C++, main.cpp aún necesitaría una definición completa de port_t para crear la instancia de "puertos". –

+1

@Matthew: puede valer la pena aclarar que es la definición_tipo_ completa la que debe estar en el archivo de encabezado; la definición de la variable va en el archivo fuente. –

15

Si desea ocultar los datos internos de la estructura port_t, puede usar una técnica como la forma en que la biblioteca estándar maneja los objetos FILE. El código de cliente solo trata con FILE* artículos, por lo que no necesitan (de hecho, generalmente no pueden) tener ningún conocimiento de lo que realmente está en la estructura FILE. El inconveniente de este método es que el código del cliente no puede simplemente declarar una variable de ese tipo; solo pueden tener punteros, por lo que el objeto debe crearse y destruirse utilizando alguna API, y todos los usos de de el objeto debe estar a través de alguna API.

La ventaja de esto es que tiene una bonita interfaz limpia de cómo se deben usar los objetos port_t, y le permite mantener las cosas privadas privadas (las cosas no privadas necesitan funciones getter/setter para que el cliente acceda a ellas).

Igual que cómo se maneja FILE I/O en la biblioteca C.

+0

Incluso la estructura FILE está claramente establecida en stdio.h. Al menos, en mi sistema. "typedef struct __sFILE {...} FILE;" A través de los punteros de FILE nunca necesitamos ver sus partes internas (que son muy interesantes - indicadores de función para leer/escribir/etc.) Pero aún ESTÁN allí. –

+0

También tenga en cuenta: Para tratar con punteros FILE * y no con los identificadores FILE *, debe usar la versión "typedef". El código anterior requiere "struct port_t". Si fuera "typedef struct port_t {...} PORT", podría usar un puntero PORT * similar a los punteros FILE *. –

+0

@Chris, no tiene que declararse por completo, una implementación podría definir técnicamente una estructura FILE como char [X] ya que no hay nada en el estándar que dicte lo que contiene la estructura, por lo que podría ocultarse. – paxdiablo

0

recomendaría una manera diferente:

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

Por lo general, no es bueno para definir variables en un archivo de cabecera.

+1

no estaba definiendo una variable en un encabezado, estaba tratando de reenviar declarar el tipo port_t. –

+0

Por qué no está usando get/set o las funciones de simulair me ganan ... Pero sí, tienes razón ... Solo estaba dando una sugerencia ... – eaanon01

6

Una solución común que utilizo:

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

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

utiliza el port_p en las interfaces de función. Usted tendrá que crear malloc especial (y gratis) envoltorios en port.h así:

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