与预处理器指令混淆
Confusion with Preprocessor Directives
我有三个文件
文件"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"
维基说
Here, the first inclusion of "grandparent.h" causes the macro
GRANDPARENT_H to be defined. Then, when "child.c" includes
"grandparent.h" the second time, the #ifndef test returns false, and
the preprocessor skips down to the #endif, thus avoiding the second
definition of struct foo. The program compiles correctly.
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
如果你手动 "expand" 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
宏。它是空的,但这并不重要,重要的是它是 defined.
然后,代码定义您的结构...
当预处理器遇到第二个 #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;
};
就是这样!
我有三个文件
文件"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"
维基说
Here, the first inclusion of "grandparent.h" causes the macro GRANDPARENT_H to be defined. Then, when "child.c" includes "grandparent.h" the second time, the #ifndef test returns false, and the preprocessor skips down to the #endif, thus avoiding the second definition of struct foo. The program compiles correctly.
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
如果你手动 "expand" 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
宏。它是空的,但这并不重要,重要的是它是 defined.
然后,代码定义您的结构...
当预处理器遇到第二个 #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;
};
就是这样!