C语言 将 .h 文件与 .c 与 #ifdef 头文件连接起来

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14290026/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 05:00:10  来源:igfitidea点击:

Linking .h files with .c with #ifdef header guards

cmultiple-inclusions

提问by lemoncodes

im having trouble linking .h and .c files, i've also read some threads regarding this problem and all of them is a bit vague and still i can't fully grasp the concept of it, and im having a lot of linking problems, Say i have b.c and b.h which i will use in a.c, and im confused whether to include b.h both a.c and b.c cuz b.c itself needs to know the structure defined in b.h, i have some function which has its prototype in b.h and is defined in b.c which also use the structure in b.h, im am not including b.h in b.c cuz as what i know b.h is more like an interface to a.c which will use the functions in b.c... Here a more clear example

我在链接 .h 和 .c 文件时遇到问题,我也阅读了一些关于这个问题的线程,所有这些都有些模糊,但我仍然无法完全理解它的概念,而且我有很多链接问题,假设我有 bc 和 bh,我将在 ac 中使用它们,我很困惑是否同时包含 bh ac 和 bc 因为 bc 本身需要知道 bh 中定义的结构,我有一些函数,它的原型在 bh 中并已定义在 bc 中也使用 bh 中的结构,我没有在 bc 中包含 bh 因为我知道 bh 更像是 ac 的接口,它将使用 bc 中的函数......这里有一个更清晰的例子

b.h file

.bh 文件

typedef struct{
int x, y;
}myStruct;

void funct1(myStruct);
void funct2(myStruct);

b.c file

.bc 文件

void funct1(myStruct x)
{
    //do something
}

void funct2(myStruct y)
{
     //do something
} 

a.c file

ac文件

#include "b.h"

int main()
{
myStruct x;
  funct1(x);
  funct2(y);
return 0;
}

Executed the command in cygwin: gcc b.c a.c -g

在cygwin中执行命令:gcc bc ac -g

Now the confusing part, i have a linking error wherein when b.c is compiled it can't detect the structure and the prototypes in b.h. Cuz all i know is that b.h is used to link b.c from a.c but when both .c is compiled it seems that b.c can't find its strucutre and prototypes,

现在令人困惑的部分,我有一个链接错误,其中当编译 bc 时,它无法检测 bh 中的结构和原型,因为我只知道 bh 用于从 ac 链接 bc,但是当两个 .c 都被编译时,它似乎bc 找不到它的结构和原型,

Why didn't i include b.h in b.c?Answer: Cuz as what i know, b.h is already included in a.c and when i include it again in b.c, i'll be doing double inclusions <--- thats what i learn so far and i know there is #ifdef but it seems it won't work, maybe i still don't know how to use it, if you know please feel free to discuss this.

为什么我没有在 bc 中包含 bh?:因为据我所知,bh 已经包含在 ac 中,当我再次将它包含在 bc 中时,我将进行双重包含 <--- 这就是我目前学到的内容,我知道有 #ifdef 但似乎它不起作用,也许我仍然不知道如何使用它,如果您知道请随时讨论。

If you have any idea as to how to go about this feel free to tell me some.

如果您对如何进行此操作有任何想法,请随时告诉我。

there is a #ifdef directive but i can't seem to have any idea how to do this.

有一个 #ifdef 指令,但我似乎不知道如何做到这一点。

NOTE: ASSUME THAT ALL ABOVE CODES IS SYNTACTICALLY CORRECT if there are any misspelled word please ignore, i'm only after the inclusions between .h and .c

注意:假设所有上述代码在语法上都是正确的,如果有任何拼写错误的单词请忽略,我只是在 .h 和 .c 之间的包含之后

回答by JBentley

You do indeed need to #include b.hin b.c. Each file is compiled separately before the linker takes over, so it doesn't matter that you have included b.h in a.c, because b.c is compiled by itself and has no idea about the contents of b.h unless you include it.

你确实需要#include b.hb.c. 每个文件在链接器接管之前单独编译,所以你在 ac 中包含 bh 没有关系,因为 bc 是自己编译的,除非你包含它,否则不知道 bh 的内容。

Here's an example of a #includeguard

这是一个#include守卫的例子

// some_header_file.h
#ifndef SOME_HEADER_FILE_H
#define SOME_HEADER_FILE_H
// your code
#endif

When some_header_file.h is included anywhere, everything in between the #ifndefand the #endifwill be ignored if SOME_HEADER_FILE_H has been defined, which will happen on the first time it is included in the compilation unit.

当 some_header_file.h 包含在任何地方时,如果 SOME_HEADER_FILE_H 已定义,则#ifndef和之间的所有内容都#endif将被忽略,这将在第一次包含在编译单元中时发生。

It is common practice to name the #defineafter the name of the file, to ensure uniqueness within your project. I like to prefix it with the name of my project or namespace as well, to reduce the risk of clashes with other code.

通常的做法#define是在文件名之后命名,以确保项目中的唯一性。我也喜欢用我的项目或命名空间的名称作为前缀,以减少与其他代码冲突的风险。

NOTE: The same header file CAN be included multiple times within your project even with the above include guard, it just can't be included twice within the same compilation unit. This is demonstrated as follows:

注意:即使使用上述包含保护,相同的头文件也可以在您的项目中多次包含,它不能在同一个编译单元中包含两次。这证明如下:

// header1.h
#ifndef HEADER_H
#define HEADER_H
int test1 = 1;
#endif

// header2.h
#ifndef HEADER_H
#define HEADER_H
int test2 = 2;
#endif

Now let's see what happens when we try to include the above two files. In a single compilation unit:

现在让我们看看当我们尝试包含上述两个文件时会发生什么。在单个编译单元中:

// a.cpp
#include "header1.h"
#include "header2.h"
#include <iostream>
int main()
{
   std::cout << test1;
   std::cout << test2;
};

This generates a compiler error because test2 is not defined - it is ignored in header2.h because HEADER_H is already defined by the time that is included. Now if we include each header in separate compilation units:

这会生成编译器错误,因为 test2 未定义 - 它在 header2.h 中被忽略,因为 HEADER_H 已在包含的时间定义。现在,如果我们将每个头文件包含在单独的编译单元中:

// a.cpp
#include "header2.h"
int getTest2()
{
   return test2;
};

// b.cpp
#include "header1.h"
#include <iostream>
int getTest2(); // forward declaration
int main()
{
   std::cout << test1;
   std::cout << getTest2();
};

It compiles fine and produces the expected output (1 and 2), even though we are including two files which both define HEADER_H.

它编译良好并产生预期的输出(1 和 2),即使我们包含两个都定义 HEADER_H 的文件。

回答by William Seiti Mizuta

You need to include b.hin all files that uses the structures that are defined in b.h. So you need to put a #include <b.h>in both files. To avoid that b.his loaded several times, you need the directives #ifdef. In your case:

您需要b.h在所有使用b.h. 所以你需要#include <b.h>在两个文件中都放一个。为了避免b.h多次加载,您需要指令#ifdef。在你的情况下:

b.h

#ifndef B_H
#define B_H

typedef struct{
    int x, y;
}myStruct;

void funct1(myStruct);
void funct2(myStruct);

#endif

and b.c:

和公元前:

#include "b.h"

void funct1(myStruct x)
{
    //do something
}

void funct2(myStruct y)
{
     //do something
} 

回答by BenjiWiebe

Proper coding would have you include b.h in b.c.

正确的编码会让你在 bc 中包含 bh

Here is a header guard that should work:

这是一个应该可以工作的头卫:

#ifndef B_H_INCLUDED
#define B_H_INCLUDED
//header file
#endif

Put your declarations where the comment is, and include everywhere you need to.

将您的声明放在注释所在的位置,并包括您需要的任何地方。

EDIT The way I understand it, is that gcccompiles b.c first, because a.c depends on b.c. But when it compiles b.c first, b.h has not yet been included.

编辑我理解的方式是gcc先编译 bc ,因为 ac 取决于 bc 但是当它首先编译 bc 时, bh还没有被包含

回答by Remy Lebeau

You need to #includeb.h in b.c. It is not just an interface for a.c, b.c needs to know the same definitions for its own code as well. Your reason for not including b.h in b.c is wrong. Each .c file is compiled separately from every other .c file. When the compiler is done with a.c, it starts over fresh with b.c. It does not matter that a.c included b.h, because b.c has no concept that a.c even exists. The purpose of a header guard is to prevent a .h file from being processed repeat times if it is included multiple times while compiling a given .c file. Without the guard, declarations would get compiled multiple times, causing errors about multiple declarations of existing symbols.

您需要#include在 bc 中使用bh 这不仅仅是 ac 的接口,bc 还需要知道其自身代码的相同定义。你在 bc 中不包括 bh 的原因是错误的。每个 .c 文件都与其他 .c 文件分开编译。当编译器完成 ac 时,它会重新开始使用 bc ac 包含 bh 并不重要,因为 bc 甚至没有 ac 存在的概念。如果在编译给定的 .c 文件时多次包含 .h 文件,则头保护的目的是防止 .h 文件被重复处理。如果没有保护,声明将被多次编译,导致关于现有符号的多次声明的错误。