当已包含time.h标头时,取消引用指向不完整类型的指针

时间:2013-06-11 17:20:09

标签: c

我正在编写一个标题,timedate.h,其开头如下:

#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

然后将其包含在我的一个主要.c文件中,如下所示:

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

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

在我看来,这应该有效,因为在调用timedate.h之前,time.h包含在主代码中。但是,当我制作时,我会收到以下错误:

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

你能帮我理解发生了什么吗?我注意到如果我在timedate.h中#include <time.h>,那么错误就会消失......但为什么呢?它已经包含在file2nav.c中。

6 个答案:

答案 0 :(得分:11)

在您的文件timedate.h中使用

struct tm *time;

struct tm尚未定义。您需要包含标题#include <time.h>

您的代码中的第二个问题是您正在使用未初始化的指针time。您可以使用本地变量:

struct tm time;
time.tm_year = year;

malloc指针(记得free):

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

Ryan指出,更好的做法是在.h声明函数,并在.c定义

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

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

#endif

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

您需要包含所有头文件才能编译程序。 C++ Header order提出了一个可能的顺序:

  • 相应的头文件
  • 必要的项目标题
  • 第三方图书馆标题
  • 标准库标题
  • 系统标题

按此顺序,您不会错过任何忘记自己包含库的头文件。 (感谢Josh这一点。)

答案 1 :(得分:3)

您需要在#include <time.h>文件中timedate.h,因为函数timetounixtime使用在其中声明的结构。该函数需要知道struct tm是什么,除非包含time.h,否则它不会。这里还有其他一些问题。

您需要为tm结构分配空间:

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

但由于你只是在这一个函数中使用它,你应该只是做

struct tm time;

否则在开始分配时会使用无效内存。

此头文件应另外分为两个文件。

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

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

#endif

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

我建议您将来使用gcc -Wall进行编译。你会收到类似这样的有用警告:

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

^表示您在没有声明的情况下调用mktime函数,这是忘记time.h

的另一个症状

答案 2 :(得分:3)

您包含错误的标题,应该是<time.h>,而不是<sys/time.h>

<sys/time.h>可能只是没有定义您尝试使用的结构。

答案 3 :(得分:2)

请勿包含sys/time.htime.h

答案 4 :(得分:1)

time也恰好是系统调用。我建议将变量名time更改为其他名称,以免与系统调用发生冲突。

答案 5 :(得分:0)

您需要在头文件中包含time.h头文件,因为它不知道struct tm和mktime符号是什么。

当最终从源文件中包含time.h标头时,您需要对这些符号进行前向声明,以便它们正确链接。