C 已包含time.h标头时取消对不完整类型的引用指针
我正在写一个标题timedate.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
#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]