头文件循环引用导致“unknown type name”的问题详解

问题原因

        最近在做嵌入式项目时,编译过程中头文件爆出了“unknown type name …”的错误。经过检查,未知的变量类型所在的头文件已经被包含在本头文件中了,而且也添加进了头文件目录,通过Ctrl键也能跳转,表面看上去没有任何问题,甚至怀疑是编译器出问题了。随后,我查看了编译过程的输出,通过编译顺序发现了问题所在。

        接下来我描述一下问题具体出现的过程,假如有"a.h" "b.h" "c.h"三个头文件,内容如下:

a.h:

#ifndef _A_H
#define _A_H

#include "c.h"

typedef struct
{
    uint8 a;
    uint8 b;
}type_a;

u8 num;

b.h:

#ifndef _B_H
#define _B_H

#include "a.h"

typedef struct
{
    type_a a;
    uint8 b;
}type_b;

c.h:

#ifndef _C_H
#define _C_H

#include "b.h"

typedef struct
{
    type_b a;
    uint8 b;
}type_c;

typedef char u8;

        当然这只是个很简单的例子,在实际开发中不会出现这样看起来很呆的循环包含的情况。在这个例子中,三个头文件的包含关系是:b包含a,c包含b,而a又包含c。如果编译过程第一个走到c.h, #ifndef _C_H 语句会判断当前没有编译c.h文件,而对c.h进行编译,当执行到 #include "b.h" 这条语句的时候,会寻找名为b.h的头文件并进行编译,而这个时候,c.h中剩下的内容并没有参与编译。同理,在b.h文件中走到 #include "a.h" 这条语句时又会寻找a.h头文件进行编译。而在a.h中,由于包含了c.h头文件,编译器也会去寻找该头文件,然而 #ifndef _C_H 这条语句提示编译器c.h已经参与编译了,因此会跳出c.h的编译,回到a.h中,当继续编译到 u8 num; 时,编译器会发现之前没有编译过名为u8的类型名,最终报出"unknown type name 'u8' "的错误。

        这就是为什么我们包含头文件后明明可以跳转找到类型定义,编译器依旧报"unknown type name"的原因。

解决方案

        其实了解了原因之后,解决方法很明显:

        重新规划头文件内容,调整头文件内容,避免出现循环引用的情况。虽然这一句话看起来很简单,但实际上要对整个项目结构非常了解,熟悉项目涉及的每个头文件的作用。同时调整头文件内容后可能还需要对.c文件也做出相应修改。要是实在不会调整,就只能减少项目功能,精简头文件包含结构了。

  • 33
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值