Home > Article > Backend Development > What is the relationship between h files and c files?
h files are often placed at the head of .c (.cpp) files, so they are named "header files". The h file is a file that extracts the repeated declaration statements from the .c file, puts it in a new file, and then types a statement like "#include XXXX" into the required .c (.cpp) file.
The operating environment of this tutorial: windows7 system, C 17 version, Dell G3 computer.
In the era when the compiler only recognized .c (.cpp)) files and did not know what .h was At that time, people wrote a lot of .c (.cpp) files. Gradually, people found that the declaration statements in many .c (.cpp) files were the same, but they had to repeat them word by word. Type these contents into each .c (.cpp) file. But what's even more terrifying is that when one of the declarations is changed, all .c (.cpp) files need to be checked.
So people extract the repeated parts, put them in a new file, and then type statements like #include XXXX in the required .c (.cpp) file. In this way, even if a certain statement changes, there is no need to search and modify it everywhere. Because this new file is often placed at the head of the .c (.cpp) file, it is named "header file" and the extension is .h.
In the initial stage of learning our language, our program often only has one .c file or a few of these. At this time, we rarely encounter the headache of header file organization. As our program With the increase, the code volume has reached thousands or even tens of thousands of lines, and the number of files is also increasing. At this time, the organization of these files becomes a problem. In fact, to put it bluntly, the organization of these files is theoretically a problem of module design in software engineering, etc.
A brief description of the role of the header file:
(1) Call the library function through the header file. In many cases, it is inconvenient (or not allowed) to release the source code to users, as long as the header files and binary libraries are provided to users. Users only need to call library functions according to the interface declaration in the header file, and do not need to care about how the interface is implemented. The compiler will extract the corresponding code from the library.
(2) Header files can strengthen type safety checks. If an interface is implemented or used in a manner inconsistent with the declaration in the header file, the compiler will point out an error. This simple rule can greatly reduce the programmer's burden of debugging and correcting errors.
For example, I define a function declaration in aaa.h, and then I create aaa.c in the same directory as aaa.h. The implementation of this function is defined in aaa.c, and then #include this aaa.h in the .c file where the main function is located, and then I can use this function. When main runs, it will find the aaa.c file that defines this function. This is because the main function is the program entry point of standard C/C, and the compiler will first find the file where the function is located.
Assume that when the compiler compiles myproj.c (which contains main()), it finds that it includes mylib.h (which declares the function void test()), then the compiler will follow the preset settings The path (the include path list and the path where the code file is located) looks for an implementation file with the same name (extension .cpp or .c, in this case mylib.c), if the file is found, and the function is found in it (void test() in this example), continue compiling.
If the implementation file cannot be found in the specified directory, or the implementation code is not found in the file and subsequent include files, a compilation error will be returned. In fact, the include process can be "seen" as a In the process of file splicing, the declaration and implementation are written in the header file and the C file respectively, or both are written in the header file at the same time. In theory, there is no essential difference.
Theoretically speaking, as long as the contents in C files and header files are supported by the C language, you can write anything. For example, if you write a function body in a header file, as long as any C file contains This header file can compile this function into part of the target file (compilation is based on C files, if this header file is not included in any C file, this code will be useless), you can do it in the C file Function declaration, variable declaration, structure declaration, this is not a problem! ! ! So why must it be divided into header files and C files? And why are functions, variable declarations, macro declarations, and structure declarations generally made in headers? When defining variables in a C file, what about function implementation? ?
To understand the difference between C files and header files, you first need to understand the working process of the compiler. Generally speaking, the compiler will do the following processes:
1. Preparation Processing stage
2. Lexical and syntax analysis stage
3. Compilation stage, first compile it into pure assembly statements, and then assemble them into CPU-related binary codes to generate each target file
4. In the connection phase, the absolute address of each code segment in each target file is positioned to generate an executable file related to a specific platform. The compiler compiles in units of C files, that is to say, if If there is not a single C file in your project, then your project will not compile. The connector is based on target files. It will relocate functions and variables in one or more target files to generate the final executable file. In program development on PC, there is generally a main function, which is the convention of each compiler. In order to generate a final executable file, some target files are needed, that is, C files are needed, and these C files need a main function as the entry point of the executable program.
To put it simply, the compilation of C language is divided into preprocessing, compilation, assembly, and linking (test.c test.h => test.i => test.s => test.o = > test) four major stages. The #include macro processing in the c file will write all the contents of the h file referenced in c to the c file during the preprocessing stage, and finally generate the .i intermediate file. At this time, the contents of the h file are equivalent to being written c file.
This also provides a channel for code reuse. Many c files can reference the same h file, so that the h file will be placed in multiple c files and compiled multiple times. This is also The reason why definitions cannot be placed in h files but only declarations is that when definitions are placed, they are compiled multiple times. When the program is linked (multiple int a; strong symbol definitions are defined in the system), an error will occur. The declarations are different. The declaration It means that the extension of the definition will eventually end up in one definition, so there will be no error of repeated definition when linking.
We must have used this format in h files in programming
#ifndef XXX_H #define XXX_H //…… #endif
Haha, what is its use? It eliminates duplicate definitions when h files refer to each other. Of course, macro definitions play a role in the preprocessing stage, and there is no shadow of macros in the post-compilation process.
A.h int a(); B.h #include "A.h" C.h #include "A.h" D.h #include "A.h" #include "B.h"
There will be two statements of int a(); repeated in the above D.h file, which is a bit repetitive. At this time, the conditional compilation macro comes in handy
A.h #ifndef A_H #define A_H int a(); #endif
This way there will be no duplication of definitions.
Recommended tutorial: "C#"
The above is the detailed content of What is the relationship between h files and c files?. For more information, please follow other related articles on the PHP Chinese website!