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

不羁岁月 提交于 2019-11-28 08:29:35

You do indeed need to #include b.h in 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.

Here's an example of a #include guard

// 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 #ifndef and the #endif will be ignored if SOME_HEADER_FILE_H has been defined, which will happen on the first time it is included in the compilation unit.

It is common practice to name the #define after 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.

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:

// 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.

You need to include b.h in 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.h is loaded several times, you need the directives #ifdef. In your case:

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
} 

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

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 gcc compiles b.c first, because a.c depends on b.c. But when it compiles b.c first, b.h has not yet been included.

You need to #include b.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.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!