C language uses #ifndef structure to prevent repeated inclusion of header files

Yesterday, a fish tried to disassemble the integrated version of his homework from the component module version, but he encountered some problems. I found that she didn't use #ifndef and other macro definitions to avoid repeated inclusion of header files. Here are some detailed explanations.

1. Problems

To facilitate testing, I created a new project, which initially contains three files:

  1. main.c
  2. a.c
  3. a.h

The three documents are as follows:

main.c

#include <stdio.h>
#include <stdlib.h>
#include "a.h"
 
/* run this program using the console pauser or add your own getch, system("pause") or input loop */

int main(int argc, char *argv[]) {
	printf("in main.c !\n"); 
	test(); //Declared in a.h, defined in a.c 
	printf("N = %d\n",N); //420
	printf("a = %d\n",a); //608
	printf("b = %d\n\n",b); //728
	return 0;
}

a.c

#include <stdio.h>

void test(void)
{
	printf("test()!\n");
}

a.h

#define N 420

int a = 608;
int b = 728;

void test(void);

a.h is the header file, which stores the definitions of constant N, variables A and b and the declaration of test function. a. The C file stores the definition of the test function.

Compile and run the project without any problems. The output results are as follows

in main.c !
test()!
N = 420
a = 608
b = 728

Next, we add a header file b.h to the project

#include "a.h"
#define t(x) test(x)

And in main Add a line to C: #include "b.h":

#include <stdio.h>
#include <stdlib.h>
#include "a.h"
#include "b.h"
 
/* run this program using the console pauser or add your own getch, system("pause") or input loop */

int main(int argc, char *argv[]) {
	printf("in main.c !\n"); 
	test(); //Declared in a.h, defined in a.c 
	printf("N = %d\n",N); //420
	printf("a = %d\n",a); //608
	printf("b = %d\n\n",b); //728
	return 0;
}

There seems to be no problem. But when recompiling and running, an error is reported:

According to the prompt information of the compiler, error lies in the repeated definition of variable a.

2. Analysis

Next, let's analyze the causes of the problem.

First, let's recall the usage of #include. This is a preprocessing instruction. Before compiling, the preprocessor will first scan the file. When it finds the #include instruction, it will look for the file name in < > or "" after the instruction and include the contents of this file into the current file. The text in the included file will replace the #include instruction in the source code file, just as you type all the contents of the included file into this location in the source file.

In main C file, we use the following two instructions at the same time:

#include "a.h"
#include "b.h"

In other words, we embed all the contents of a.h and b.h into main This position of C. However, the b.h file also contains a preprocessing instruction:

#include "a.h"

This instruction once again embeds all the contents of the a.h file into main This position of C is equivalent to in main a.h. is embedded in C twice. The a.h file contains the definition of variable a:

int a = 608;

Therefore, a is repeatedly defined twice, resulting in an error.

3. Solution (using #ifndef structure)

The solution is simple. Use #ifndef structure (Macro Guard)

#Ifndef < identification >
#Define < identity >
 ......
#endif

< identity > can be freely named in theory, but the "identity" of each header file should be unique. The naming rule of identification is generally that the header file name is all capitalized, underlined before and after, and the "." in the file name It also becomes underlined, such as a.h

#ifndef _A_H_
#define _A_H_
 ......
#endif

After being included once, the macro_ A_H_ I already have it. I'll skip from #define next time_ A_H_ Code from start to #endif.

Modified main C Documents:

#include <stdio.h>
#include <stdlib.h>

#ifndef _A_H_
#define _A_H_
#include "a.h"
#endif

#ifndef _B_H_
#define _B_H_
#include "b.h"
#endif
 
/* run this program using the console pauser or add your own getch, system("pause") or input loop */

int main(int argc, char *argv[]) {
	printf("in main.c !\n"); 
	test(); //Declared in a.h, defined in a.c 
	printf("N = %d\n",N); //420
	printf("a = %d\n",a); //608
	printf("b = %d\n\n",b); //728
	return 0;
}

Modified b.h file:

#ifndef _A_H_
#define _A_H_
#include "a.h"
#endif

#define t(x) test(x)

At this time, recompile and run again, and no error will be reported. The output is as follows:

in main.c !
test()!
N = 420
a = 608
b = 728

Keywords: C

Added by WhiteShade6 on Fri, 28 Jan 2022 21:37:50 +0200