我有三个文件
档案“grandparent.h”
#ifndef GRANDPARENT_H
#define GRANDPARENT_H
struct foo {
int member;
};
#endif /* GRANDPARENT_H */
档案“parent.h”
#include "grandparent.h"
档案“child.c”
#include "grandparent.h"
#include "parent.h"
维基说
这里,第一次包含“grandparent.h”会导致宏 要定义GRANDPARENT_H。然后,当“child.c”包括时 “grandparent.h”第二次,#ifnf测试返回false,并且 预处理器向下跳到#endif,从而避免了第二个 struct foo的定义。该程序编译正确。
Q1。 “第一次加入”grandparent.h“会导致宏
GRANDPARENT_H 待定义“,所以我理解它基本上定义一个名为GRANDPARENT_H
的宏但我不明白的是该宏的内容将如何(即GRANDPARENT_H)将包含在child.c中。
我们只是定义宏GRANDPARENT_H 即
#define GRANDPARENT_H
struct foo {
int member;
};
但它的内容如何
struct foo {
int member;
};
包含在child.c中。
答案 0 :(得分:3)
如果您手动“展开”child.c
,直到没有#include
:
//grandparent.h
#ifndef GRANDPARENT_H // <- not defined at this point
#define GRANDPARENT_H // <- now it's defined
struct foo {
int member;
};
#endif /* GRANDPARENT_H */
//parent.h
//#include "grandparent.h" resolves into
//grandparent.h
#ifndef GRANDPARENT_H // <- already defined, skip until matching #endif
#define GRANDPARENT_H // <- not executed by preprocessor
struct foo { // <- not provided to the compiler
int member;
};
#endif /* GRANDPARENT_H */
现在按顺序阅读。
第一行检查是否定义了宏GRANDPARENT_H
。显然它不是,因为它是代码的第一条指令。
第二行定义了GRANDPARENT_H
宏。它是空的,但这并不重要,重要的是它是定义的。
然后,代码定义了你的结构......
当预处理器遇到第二个#ifdef GRANDPARENT_H
时,宏已经被定义,因此它会跳过文件的全部内容而不会出现任何foo redefined
错误。
使用-E
选项查看预处理的child.c
文件确认了哪一项:
$ gcc -E child.c
# 1 "child.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "child.c"
# 1 "grandparent.h" 1
struct foo {
int member;
};
# 2 "child.c" 2
# 1 "parent.h" 1
# 2 "child.c" 2
如您所见,结构只定义一次。
请注意,大多数编译器现在支持更简单的方法:只需插入
#pragma once
在文件的开头。像这样:
#pragma once
struct foo {
int member;
};
就是这样!