不包含含结构体定义的头文件是否可行?循环包含编译问题咨询
回答:移除a.h中的
#include "b.h"完全可行,且是正确解法 咱先拆解下你遇到的编译错误根源:你这是典型的头文件循环包含问题——a.h包含b.h,b.h又回头包含a.h,预处理阶段编译器会陷入循环展开,但实际处理时,当编译b.h里的sth()函数时,extern struct A aaa;这个声明还没被正确解析到,所以编译器找不到aaa,就报了 undeclared 的错误。
为什么移除a.h里的#include "b.h"可行?
因为你的struct A里只用到了struct B *b——这是一个指针类型。在C语言里,声明指向某个结构体的指针时,不需要该结构体的完整定义,只需要提前告诉编译器“存在一个名为struct B的结构体类型”(也就是前向声明)就足够了。
所以你现在移除a.h里的#include "b.h"是完全正确的,甚至可以再优化下a.h,加上struct B的前向声明让代码更清晰:
// a.h 修改后 struct B; // 前向声明struct B,告诉编译器这个类型存在 struct A { int asdf; struct B *b; }; extern struct A aaa;
额外注意事项
- 头文件保护:建议给a.h和b.h都加上头文件保护,防止后续其他文件重复包含时出问题,比如:
// a.h开头 #ifndef A_H #define A_H // 原有内容 #endif - 什么时候需要包含b.h?:如果以后你修改
struct A,需要直接使用struct B的实例(比如struct B b;而不是指针),那才需要在a.h里包含b.h,否则前向声明就足够。 - b.h的
#include "a.h"是必要的:因为b.h里的sth()函数需要访问aaa.asdf,这时候需要struct A的完整定义,所以b.h包含a.h是合理的,不会有问题。
内容的提问来源于stack exchange,提问作者Sato
相关产品推荐
相关产品推荐

