2013-06-11 7 views
5

Sto scrivendo un colpo di testa, timedate.h, che inizia come segue:dereferenziazione puntatore al tipo incompleto quando time.h intestazione è già inclusa

#ifndef _TIMEDATE_H_ 
#define _TIMEDATE_H_ 

int timetounixtime(int year, int month, int day, int hour, int minute, int second) 
{ 
    struct tm *time; 
    time->tm_year = year; 
    time->tm_mon = month; 
    time->tm_mday = day; 
    time->tm_hour = hour; 
    time->tm_min = minute; 
    time->tm_sec = second; 
    return mktime(time); 
} 

/*...*/ 

#endif 

E viene poi incluso in uno dei miei .c principale i file come segue:

#include <stdio.h> 
#include <string.h> 
#include <sys/time.h> 
#include "timedate.h" 

int main(int argv, char **argc) 
{ 
/*...*/ 
} 

mi sembra che questo dovrebbe funzionare dal time.h è incluso nel codice principale prima timedate.h è chiamato. Tuttavia, quando faccio, ottengo i seguenti errori:

XXXXXXXXXX$ make 
gcc file2nav.c -o file2nav 
In file included from file2nav.c:4:0: 
timedate.h: In function ‘timetounixtime’: 
timedate.h:10:7: error: dereferencing pointer to incomplete type 
timedate.h:11:7: error: dereferencing pointer to incomplete type 
timedate.h:12:7: error: dereferencing pointer to incomplete type 
timedate.h:13:7: error: dereferencing pointer to incomplete type 
timedate.h:14:7: error: dereferencing pointer to incomplete type 
timedate.h:15:7: error: dereferencing pointer to incomplete type 

Potete aiutarmi a capire cosa sta succedendo? Prendo atto che se ho #include <time.h> in timedate.h, l'errore scompare ... Ma perché? È già incluso in file2nav.c.

+1

Non è un compilatore di backtracking. Basta includere i file effettivamente necessari nell'intestazione. Affidarsi a includere l'ordine è un'idea orribile. –

+0

I file di intestazione sono per la dichiarazione di funzione e non la definizione di funzione. Pensa solo cosa succederebbe se tu avessi incluso quel file due volte. – mohit

+0

@EdS., Sono confuso sul motivo per cui è necessario includere nel file di intestazione, ma non devi includere #include o qualsiasi altra delle solite intestazioni di libreria standard? –

risposta

11

Nel file timedate.h si utilizza

struct tm *time; 

ma struct tm non è ancora definita. È necessario includere l'intestazione #include <time.h>.

Un secondo problema nel codice è che si sta utilizzando un puntatore non inizializzato time. È possibile utilizzare una variabile locale:

struct tm time; 
time.tm_year = year; 

o malloc un puntatore (ricordatevi di free):

struct tm* time = malloc(sizeof(struct tm)); 

Una pratica migliore, come sottolinea Ryan, è quello di dichiarare funzioni .h e definire loro in .c:

/* timedate.h */ 
#ifndef _TIMEDATE_H_ 
#define _TIMEDATE_H_ 

int timetounixtime(int year, int month, int day, int hour, int minute, int second); 

#endif 

e

/* timedate.c */ 
#include "timedate.h" 
#include <time.h> 

int timetounixtime(int year, int month, int day, int hour, int minute, int second) 
{ 
    struct tm time; 
    time.tm_year = year; 
    time.tm_mon = month; 
    time.tm_mday = day; 
    time.tm_hour = hour; 
    time.tm_min = minute; 
    time.tm_sec = second; 
    return mktime(time); 
} 

è necessario includere tutti i file di intestazione per rendere il vostro programma di compilazione. C++ Header order suggerisce un possibile ordine:

  • file di intestazione corrisposto
  • necessarie intestazioni progetto
  • 3rd librerie di parti intestazioni
  • librerie standard headers
  • intestazioni di sistema

In questo modo si vuole non perdere nessuno dei tuoi file di intestazione che si sono dimenticati di includere le librerie da soli. (Grazie a Josh per questo punto).

+0

Suppongo che abbia pensato che sarebbe stato definito avendo "" incluso nel suo file principale. – Kninnug

+0

@Kninnug, sì, questo è quello che stavo pensando, e non capisco ancora perché non sia così. La mia comprensione è che il preprocessore inserisce il testo di time.h nel file .c, prima dell'inserimento del testo del mio file di intestazione, così quando il compilatore arriva a quella parte del codice, dovrebbe aver già letto la definizione di tm. –

+0

@Yang anche, ho apportato la modifica a una variabile locale. Non sono sicuro di cosa stavo facendo lì.Devo andare a prendere una caffettiera per il mio ufficio. –

1

time è anche una chiamata di sistema. Suggerirò di cambiare il nome della variabile time in qualcos'altro per non causare un conflitto con la chiamata di sistema.

+0

Fatto. Avrei dovuto saperlo. Grazie! –

+0

Questo non risponde alla domanda dell'OP. – alk

3

È necessario #include <time.h> in voi timedate.h file perché la funzione timetounixtime utilizza una struttura dichiarata in esso.Questa funzione deve sapere che cos'è un struct tm e non a meno che non si includa lo time.h. Ci sono molti altri problemi qui però.

è necessario allocare spazio per il vostro struct tm come tale:

struct tm *time = malloc(sizeof *time); 

ma dal momento che si sta utilizzando solo in questo una funzione, si dovrebbe solo essere facendo

struct tm time; 

altrimenti si stai usando una memoria non valida quando inizi ad assegnare.

Questo file di intestazione deve essere separato in due file, in aggiunta.

/* timedate.h */ 
#ifndef _TIMEDATE_H_ 
#define _TIMEDATE_H_ 

int timetounixtime(int year, int month, int day, int hour, int minute, int second); 

#endif 

e

/* timedate.c */ 
#include "timedate.h" 

int timetounixtime(int year, int month, int day, int hour, int minute, int second) 
{ 
    struct tm time; 
    time.tm_year = year; 
    time.tm_mon = month; 
    time.tm_mday = day; 
    time.tm_hour = hour; 
    time.tm_min = minute; 
    time.tm_sec = second; 
    return mktime(time); 
} 

suggerisco in futuro si compila con gcc -Wall. Otterrete utili avvisi come questo:

timedate.h:15:3: warning: implicit declaration of function 'mktime' [-Wimplicit-function-declaration] 

^che significa che si sta chiamando la funzione mktime senza mai dichiararlo, un altro sintomo di dimenticare time.h

+0

Ho fatto questo, apportando modifiche alla mia pagina. Grazie. –

+2

qualcuno si preoccuperebbe di dirmi perché questo è downvoted? –

+0

+1 per aver menzionato la separazione dell'intestazione. – Yang

0

È necessario includere l'intestazione time.h da il file di intestazione perché non saprà cosa sono i simboli struct tm e mktime.

È necessario inoltrare dichiarazioni di tali simboli affinché possano collegarsi correttamente quando l'intestazione time.h viene infine inclusa nel file di origine.

2

Non includere sys/time.h ma time.h.

3

Si include l'intestazione errata, dovrebbe essere <time.h>, non <sys/time.h>.

<sys/time.h> probabilmente non definisce la struttura che si sta tentando di utilizzare.

+0

L'errore si presenta ancora, ma ho comunque apportato la modifica a time.h. –

Problemi correlati