繁体   English   中英

与预处理器指令混淆

[英]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"

维基说

在此,“ grandparent.h”的第一个包含将导致定义宏GRANDPARENT_H。 然后,当“ child.c”第二次包含“ grandparent.h”时,#ifndef测试返回false,并且预处理器跳至#endif,从而避免了对struct foo的第二个定义。 程序正确编译。

Q1。 ““ grandparent.h”的第一个包含将导致 GRANDPARENT_H 被定义 “,所以我了解我基本上定义了一个名为GRANDPARENT_H的宏,但我不明白的是,该宏的内容(即GRANDPARENT_H)将如何被包括在孩子中c。

我们只是在定义宏GRANDPARENT_H,即

#define GRANDPARENT_H

struct foo {
    int member;
};

但是它的内容如何

struct foo {
    int member;
};

被包括在孩子中

如果您手动“扩展” 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;
};

而已!

暂无
暂无

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

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