简体   繁体   English

与预处理器指令混淆

[英]Confusion with Preprocessor Directives

I have three files 我有三个档案

File "grandparent.h" 文件“ grandparent.h”

#ifndef GRANDPARENT_H
#define GRANDPARENT_H

struct foo {
    int member;
};

#endif /* GRANDPARENT_H */

File "parent.h" 文件“ parent.h”

#include "grandparent.h"

File "child.c" 文件“ child.c”

 #include "grandparent.h"
 #include "parent.h"

Wiki says 维基说

Here, the first inclusion of "grandparent.h" causes the macro GRANDPARENT_H to be defined. 在此,“ grandparent.h”的第一个包含将导致定义宏GRANDPARENT_H。 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. 然后,当“ child.c”第二次包含“ grandparent.h”时,#ifndef测试返回false,并且预处理器跳至#endif,从而避免了对struct foo的第二个定义。 The program compiles correctly. 程序正确编译。

q1. Q1。 "the first inclusion of "grandparent.h" causes the macro GRANDPARENT_H to be defined ", So what i understand i its basically defining a macro named GRANDPARENT_H but what i dont understand is that how will the content of that macro (ie GRANDPARENT_H) would be included in the child.c. ““ grandparent.h”的第一个包含将导致 GRANDPARENT_H 被定义 “,所以我了解我基本上定义了一个名为GRANDPARENT_H的宏,但我不明白的是,该宏的内容(即GRANDPARENT_H)将如何被包括在孩子中c。

We are just defining the macro GRANDPARENT_H ie 我们只是在定义宏GRANDPARENT_H,即

#define GRANDPARENT_H

struct foo {
    int member;
};

but how will its content ie 但是它的内容如何

struct foo {
    int member;
};

be included in the child.c 被包括在孩子中

If you "expand" child.c manually until there are no #include left: 如果您手动“扩展” 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 */

now read it sequentially. 现在按顺序阅读。 The first line checks if macro GRANDPARENT_H is defined. 第一行检查是否定义了宏GRANDPARENT_H Obviously it is not, as it's the first instruction of the code. 显然不是,因为它是代码的第一条指令。

The second line defines GRANDPARENT_H macro. 第二行定义GRANDPARENT_H宏。 It's empty but that's no important, what's important is that it is defined . 它是空的,但这并不重要,重要的是已定义它。

Then, the code defines your struct... 然后,代码定义了您的结构...

When the preprocessor encounters the second #ifdef GRANDPARENT_H , the macro is already defined, so it skips the whole contents of the file and you don't get any foo redefined error. 当预处理器遇到第二个#ifdef GRANDPARENT_H ,宏已经定义好了,因此它将跳过文件的全部内容,并且不会出现任何foo redefined错误。

Which is confirmed by using -E option to see preprocessed child.c file: 使用-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

as you can see, the structure is only defined once. 如您所见,该结构仅定义一次。

Note that most compilers now support a simpler way to do this: just insert 请注意,现在大多数编译器都支持一种更简单的方法:只需插入

#pragma once

at the start of your file. 在文件的开头。 Like this: 像这样:

#pragma once

struct foo {
    int member;
};

that's it! 而已!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM