在编写一个文件较多的单片机程序时,为了在一个文件中定义的变量或宏能被另一个文件使用,经常会写成在多个头文件相互包含,由此将可能会导致明明已经定义的宏,且已经将宏所在的文件使用 #include 包含,编译时仍会报错未定义。
先来看一段简单的代码
main.c
#include "main.h"
void SystemInit(void)
{
}
int main(void)
{
}
main.h
#ifndef __MAIN_H_
#define __MAIN_H_
#endif
lk.c
#include "lk.h"
unsigned char Admin_num;
lk.h
#ifndef __LK_H_
#define __LK_H_
#include "head.h"
#define MAX_LEN (32)
#define KEY_LEN (32)
#endif
fp.c
#include "fp.h"
FP_TypeDef User_Data;
fp.h
#ifndef __FP_H_
#define __FP_H_
#include "head.h"
typedef struct
{
unsigned char id;
unsigned char key[MAX_LEN];
}FP_TypeDef;
#endif
head.h
#ifndef __HEAD_H_
#define __HEAD_H_
#include "fp.h"
#include "lk.h"
#endif
此时编译将会报错 ,提示在fp.h文件中 MAX_LEN 没有定义
我们单个C文件编译,发现,fp.c能通过, lk.c 文件居然报错
lk.c 看上去并没有什么错误为什么会报错呢,而且fp.h文件中用到的 MAX_LEN 已经通过head.h文件将 lk.h文件包含进入,MAX_LEN 是在lk.h文件中定义的,为什么还会提示在fp.h文件中未定义MAX_LEN ??
原因分析
我们将 lk.c 中所有的 #include 全部用对应的头文件层层替换,得到的代码为:
1、lk.c原文
#include "lk.h"
unsigned char Admin_num;
2、用lk.h 中的内容替换 #include "lk.h"
//#ifndef __LK_H_ //前面没有定义过__LK_H_,所以编译 #ifndef 到 #endif 的内容
#define __LK_H_
#include "head.h"
#define MAX_LEN (32)
#define KEY_LEN (32)
//#endif
unsigned char Admin_num;
3、用head.h 中的内容替换 #include "head.h"
//#ifndef __LK_H_ //前面没有定义过 __LK_H_,所以编译 #ifndef 到 #endif 的内容
#define __LK_H_
//#ifndef __HEAD_H_ //前面没有定义过 __HEAD_H_,所以编译 #ifndef 到 #endif 的内容
#define __HEAD_H_
#include "fp.h"
#include "lk.h"
//#endif
#define MAX_LEN (32)
#define KEY_LEN (32)
//#endif
unsigned char Admin_num;
4、用fp.h 中的内容替换 #include "fp.h"
//#ifndef __LK_H_ //前面没有定义过 __LK_H_,所以编译 #ifndef 到 #endif 的内容
#define __LK_H_
//#ifndef __HEAD_H_ //前面没有定义过 __HEAD_H_,所以编译 #ifndef 到 #endif 的内容
#define __HEAD_H_
//#ifndef __FP_H_ //前面没有定义过 __FP_H_,所以编译 #ifndef 到 #endif 的内容
#define __FP_H_
#include "head.h"
typedef struct
{
unsigned char id;
unsigned char key[MAX_LEN];
}FP_TypeDef;
//#endif
#include "lk.h"
//#endif
#define MAX_LEN (32)
#define KEY_LEN (32)
//#endif
unsigned char Admin_num;
5、用head.h 中的内容替换 #include "head.h"
//#ifndef __LK_H_ //前面没有定义过 __LK_H_,所以编译 #ifndef 到 #endif 的内容
#define __LK_H_
//#ifndef __HEAD_H_ //前面没有定义过 __HEAD_H_,所以编译 #ifndef 到 #endif 的内容
#define __HEAD_H_
//#ifndef __FP_H_ //前面没有定义过 __FP_H_,所以编译 #ifndef 到 #endif 的内容
#define __FP_H_
//#ifndef __HEAD_H_ //前面已经定义过 __HEAD_H_,所以不再编译 #ifndef 到 #endif 的内容
/*#define __HEAD_H_
#include "fp.h"
#include "lk.h"
*/
//#endif
typedef struct
{
unsigned char id;
unsigned char key[MAX_LEN];
}FP_TypeDef;
//#endif
#include "lk.h"
//#endif
#define MAX_LEN (32)
#define KEY_LEN (32)
//#endif
unsigned char Admin_num;
6、用lk.h 中的内容替换 #include "lk.h"
//#ifndef __LK_H_ //前面没有定义过 __LK_H_,所以编译 #ifndef 到 #endif 的内容
#define __LK_H_
//#ifndef __HEAD_H_ //前面没有定义过 __HEAD_H_,所以编译 #ifndef 到 #endif 的内容
#define __HEAD_H_
//#ifndef __FP_H_ //前面没有定义过 __FP_H_,所以编译 #ifndef 到 #endif 的内容
#define __FP_H_
//#ifndef __HEAD_H_ //前面已经定义过 __HEAD_H_,所以不再编译 #ifndef 到 #endif 的内容
/*#define __HEAD_H_
#include "fp.h"
#include "lk.h"
*/
//#endif
typedef struct
{
unsigned char id;
unsigned char key[MAX_LEN];
}FP_TypeDef;
//#endif
//#ifndef __LK_H_ //前面已经定义过 __LK_H_,所以不再编译 #ifndef 到 #endif 的内容
/*#define __LK_H_
#include "head.h"
#define MAX_LEN (32)
#define KEY_LEN (32)
*/
//#endif
//#endif
#define MAX_LEN (32)
#define KEY_LEN (32)
//#endif
unsigned char Admin_num;
7、去掉所有注释,lk.c中最终的内容为:
#define __LK_H_
#define __HEAD_H_
#define __FP_H_
typedef struct
{
unsigned char id;
unsigned char key[MAX_LEN];
}FP_TypeDef;
#define MAX_LEN (32)
#define KEY_LEN (32)
unsigned char Admin_num;
可以发现, 结构体中用到的 MAX_LEN 在前面并没有定义,而是在后面定义的,最终导致编译错误。
重复包含头文件,会使后面定义的内容,被前面的条件编译忽略,导致不被编译。文章来源:https://www.toymoban.com/news/detail-443612.html
解决方法
将 #include 语句放在所有宏定义之后文章来源地址https://www.toymoban.com/news/detail-443612.html
到了这里,关于关于C/C++语言重复包含头文件,编译时报错已定义的宏未定义的原因及解决方法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!