Frank Harris
Frank Harris

Reputation: 305

dereferencing pointer to incomplete type when time.h header is already included

I'm writing a header, timedate.h, which begins as follows:

#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

And is then included in one of my main .c files as follows:

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

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

It seems to me that this should work since time.h is included in the main code before timedate.h is called. However, when I make, I get the following errors:

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

Can you help me understand what's going on? I note that if I #include <time.h> in timedate.h, the error goes away...But why? It's already included in file2nav.c.

Upvotes: 5

Views: 6038

Answers (6)

Ryan Haining
Ryan Haining

Reputation: 36882

You need to #include <time.h> in you timedate.h file because the function timetounixtime uses a struct declared in it. That function needs to know what a struct tm is, and it doesn't unless you include time.h. There are several other problems here though.

You need to allocate space for your tm struct as such:

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

but since you're only using it in this one function, you should just be doing

struct tm time;

otherwise you're using invalid memory when you start assigning.

This header file should be separated into two files, additionally.

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

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

#endif

and

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

I suggest in the future you compile with gcc -Wall. You'll get useful warnings like this one:

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

^which means you are calling the mktime function without ever declaring it, another symptom of forgetting time.h

Upvotes: 3

Yang
Yang

Reputation: 8170

In your file timedate.h you use

struct tm *time;

but struct tm is not defined yet. You need to include the header #include <time.h>.

A second problem in your code is that you're using an uninitialized pointer time. You can use a local variable:

struct tm time;
time.tm_year = year;

or malloc a pointer (remember to free):

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

A better practice, as Ryan points out, is to declare functions in .h and define them 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

and

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

You need to include all header files to make your program compile. C++ Header order suggests one possible order:

  • corresponded header file
  • necessary project headers
  • 3rd party libraries headers
  • standard libraries headers
  • system headers

In this order you will not miss any of your header files that forgot to include libraries by their own. (Thank Josh for this point).

Upvotes: 11

sth
sth

Reputation: 229754

You include the wrong header, it should be <time.h>, not <sys/time.h>.

<sys/time.h> probably simply doesn't define the struct you are trying to use.

Upvotes: 3

alk
alk

Reputation: 70971

Do not include sys/time.h but time.h.

Upvotes: 2

bojangler
bojangler

Reputation: 544

You need to include the time.h header from the header file because it won't know what the struct tm and mktime symbols are.

You would need forward declarations of those symbols in order for them to link properly when the time.h header eventually gets included from your source file.

Upvotes: 0

unxnut
unxnut

Reputation: 8839

time also happens to be a system call. I'll suggest changing the variable name time to something else so as not to cause a conflict with the system call.

Upvotes: 1

Related Questions