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

C 已包含time.h标头时取消对不完整类型的引用指针,c,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 = d

我正在写一个标题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
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include "timedate.h"

int main(int argv, char **argc)
{
/*...*/
}
然后包含在我的一个主.c文件中,如下所示:

#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
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include "timedate.h"

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

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

在您使用的文件
timedate.h

struct tm *time;
但是还没有定义
struct tm
。您需要包含标题
#include

代码中的第二个问题是使用了未初始化的指针
time
。可以使用局部变量:

struct tm time;
time.tm_year = year;
或者
malloc
指针(记住
free
):

正如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.h */
#ifndef _TIMEDATE_H_
#define _TIMEDATE_H_

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

#endif

/*timedate.c*/
#包括“timedate.h”
#包括
int timetounixtime(整数年、整数月、整数天、整数小时、整数分钟、整数秒)
{
结构时间;
time.tm_year=年;
time.tm_mon=月份;
time.tm_mday=天;
time.tm_hour=小时;
time.tm_min=分钟;
time.tm_sec=秒;
返回时间(time);
}
您需要包含所有头文件,以使程序能够编译。建议一种可能的顺序:

  • 对应的头文件
  • 必要的项目标题
  • 第三方库标题
  • 标准库标题
  • 系统标题

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

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

您需要在
timedate.h
文件中包含
,因为函数
timetounixtime
使用了其中声明的结构。该函数需要知道什么是
struct tm
,除非包含
time.h
。不过,这里还有其他几个问题

您需要为tm结构分配空间,如下所示:

struct tm *time = malloc(sizeof *time);
但是,由于您只在这一个函数中使用它,所以您应该这样做

struct tm time;
否则,开始分配时使用的内存无效

此外,此头文件应分为两个文件

我建议将来使用
gcc-Wall
进行编译。您将得到如下有用的警告:

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

^这意味着您在调用
mktime
函数时从未声明它,这是忘记
time.h

的另一个症状,您需要从头文件中包含time.h头,因为它不知道struct tm和mktime符号是什么


当time.h头最终从源文件中包含时,您需要转发这些符号的声明,以便它们正确链接。

不要包含
sys/time.h
,而是
time.h

如果包含了错误的头,应该是
,而不是


可能只是没有定义您试图使用的结构。

它不是回溯编译器。只需在标题中包含您实际需要的文件。依赖包含顺序是一个可怕的想法。头文件用于函数声明,而不是函数定义。试想一下,如果您包含该文件两次,会发生什么情况。@EdS,我不明白为什么您必须#包含在头文件中,但您不必#包含或任何其他常用的标准库头?
timetounixtime
最好返回
time\u t
@FrankHarris:您必须有定义(或在某些情况下,至少提前声明)你实际使用的这些东西。它们必须是有序的。编译器不会忽略和错误,它将在将来得到纠正。如果你在代码中创建一个
tm
或取消引用一个
tm*
,你必须事先有
tm
的定义。我猜他认为它将由havin定义g
包含在他的主文件中。@Kninnug,是的,这就是我所想的,我还不明白为什么不是这样。我的理解是,预处理器在插入头文件的文本之前,将time.h的文本插入到.c文件中,所以当编译器到达代码的那一部分时,它应该已经被重新编译了ady阅读tm的定义。@Yang另外,我对一个局部变量进行了更改。我不确定我在那里做了什么。我需要为我的办公室买一个咖啡壶。@FrankHarris:
是不同的文件。一个小建议是,如果在实现中首先包含用户头,最后包含系统头,那么您就不太容易被忽略我很希望有顺序相关的行为。完成。我应该知道这一点。谢谢!这并没有回答OP的问题。错误仍然出现,但我更改了时间。无论如何。
/* 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);
}
timedate.h:15:3: warning: implicit declaration of function 'mktime' [-Wimplicit-function-declaration]