头文件可以防什么错?运用头文件做声明

发布时间:2026/10/8 14:26:49
头文件可以防什么错?运用头文件做声明 参考Andrew Koenig《C 陷阱与缺陷第二版》4.6节目录书上的例子file.h 和 file.cfile.c 里其实有两个声明这样写的效果直观演示如果一个函数忘了声明编译器把它当成返回int的函数照单全收连接器对类型不匹配毫无反应。类型错了没人管谁来管书 4.6 开头给出答案每个外部对象只在一个地方声明。这个地方一般就是一个头文件所有用到它的模块都 include 这个头文件。特别要指出的是定义它的那个模块也应该 include 这个头文件。这条规则为什么能堵住这个洞先看书是怎么用的书上的例子file.h 和 file.c书里接着用 4.1 提过的filename例子一个多模块程序每个模块都要知道同一个文件名希望只改一处、所有模块同时更新。第一步建一个头文件file.h里面只有声明extern char filename[];第二步所有用到filename的源文件都加上#include file.h第三步选一个源文件给出初值不妨叫file.c#include file.h char filename[] /etc/passwd;file.c 里其实有两个声明file.c里的 include 展开会看到filename出现了两次extern char filename[]; char filename[] /etc/passwd;一个声明一个定义堆在同一个文件里。这合法吗判定条件是两句只要各声明是一致的而且其中最多只有一个定义这样写就合法。extern char filename[];和char filename[] /etc/passwd;类型一致、定义只有一个——合法。这样写的效果书最后点出这样做为什么值头文件声明了filename的类型于是每个 include 它的模块自动把类型声明对了file.c定义了filename因为它也 include 了头文件定义的类型自动和声明相符。编译所有文件filename的类型就肯定是正确的。声明的类型只有一份谁也没机会抄错。直观演示故意让两边不一致——head.h声明n是intextern int n;conf.c定义n是字符数组但它 include 了头文件#include head.h char n[] xyz;编译conf.c当场报错conf.c(4): error C2040: n:char [0]与int的间接寻址级别不同两个冲突的声明出现在同一个编译单元里编译器看得见两个一比对就报 C2040。错在编译期程序根本没机会运行。没头文件同样的漂移没人管。把冲突拆到两个文件。d1.c/* defines n as a char array */ char n[] xyz;d2.c一口咬定n是int#include stdio.h extern int n; int main(void) { printf(n %d\n, n); return 0; }编译d1.c d2.c零警告链接通过运行退出码 0打印n 8026488xyz被当成了 8026488。这不是随机的垃圾数字——xyz\0在内存里是四个字节78 79 7A 00d2.c按小端把前四个字节读成一个int就是0x007A7978 8026488。每次运行都是这个数地址会变值不会。这一组对照就是 4.6 的全部意义声明漂移的结局声明只有一份头文件error C2040编译期拦下声明各抄一份无头文件编译零警告、链接通过运行期读出 8026488