Summary of usage rules of code header files and preprocessing analysis of header files

Modular programming requirements for header files

In modular programming, it is very common to use header files. Header files usually contain information such as constants, macro definitions, type definitions, function names, etc., which can make the code more modular, more readable, and more maintainable. powerful.

The following are some even file usage rules that should be observed in modular programming.

1. Only include the required header files. The number and size of the header files will directly affect the compilation time and readability. In order to avoid unnecessary overhead, only the required header files should be included.

2. Do not define variables in header files: header files should only contain information such as constants, macro definitions, type definitions, and function names. Variables should not be defined in header files, which will cause variables to be defined multiple times and cause link errors.

3. Avoid circular inclusion. When header file A includes header file B, and header file B also includes header file A, a circular inclusion will occur, which will lead to compilation errors. However, in practice, if you completely avoid circular dependencies, you need to develop The reader has a very clear understanding of the topological inclusion relationship of the header file, which is usually impossible, so technically the GUARD macro can be used to solve the header file circular inclusion relationship.

4. Use include guard. Using include guard in header files can prevent header files from being included multiple times. Include guard is usually implemented using macro definitions and conditional compilation to ensure that header files are only included once.

5. Use conditional compilation, you can use conditional compilation in the header file to control the inclusion of the header file, for example, you can use #ifdef and #ifndef to avoid including the same header file multiple times.

6. Following the clear specification, the naming of header files should follow certain rules, such as using lowercase letters and underscores, or using uppercase letters and underscores to separate words, which can make header files easier to identify and use.

7. Use standard library header files. When writing code, you should use standard library header files as much as possible, such as stdio.h, stdlib.h, etc., and avoid using system-specific header files.

8. The source code should avoid introducing API declarations that they do not need. If there is, it means that a header file is too coupled, or a large and comprehensive header file appears. In this case, the large header file is broken down into multiple small header files with independent functions to be included. Reduce coupling and improve cohesion, which is equivalent to replacing stereotype printing with movable type printing.

Complying with these header file usage rules can make the code structure clearer, more readable, more maintainable, and help developers write high-quality modular code.

Should header files satisfy the bootstrap principle?

Yes, header files should satisfy the self-contained principle, which means that a header file should be able to be compiled and used independently without depending on other header files or source files.

If a header file does not meet the bootstrapping principle, then other header files need to be included in the source file that includes it, which will lead to poor readability and maintainability of the code. In addition, if the header file contains content is unclear or insufficient, and may cause compile errors or run-time errors.

In order to meet the bootstrap principle, the header file should contain all the type definitions, macro definitions, constants and other information it needs, while not including unnecessary information, the header file should be independent, reusable, and can be used in different projects Use. Can also be used in combination with other header files.

In actual programming, we can satisfy the bootstrap principle through the following aspects:

1. Avoid using the contents of other header files, unless these contents are necessary.

2. Include the header file in the ifndef and endif macro definitions to avoid repeated inclusion.

3. Declare variables and functions in the header file instead of defining them to avoid repeated definitions and link errors.

4. Organize the definitions and declarations in the header file logically to avoid confusion and redundancy.

5. Comply with naming conventions, give meaningful names, and write high-quality code.

Projects that meet the header file bootstrapping principles can make header files clearer, more maintainable, and easier to use.

The header file contains logic analysis

Take the linux kernel as the analysis object, and get the preprocessing file of init/main.c source code.

View the main.i file

The first line indicates the preprocessed source code file, that is, main.c, and the fourth line kconfig.h is not the header file included in main.c, but is introduced through the -include compiler option on the command line. can be compiled by command

make init/main.i V=1

Check the build details for verification. The next line indicates that the first 1 indicates the first line of ././include/linux/kconfig.h. Since it is imported from the command line, the order is the largest, and the number of lines is 1. The 1 at the end indicates new Include the beginning of the file kconfig.h, check its content is indeed the first line (excluding guard), including the autoconf.h file.

Immediately afterwards, it indicates the beginning of autoconf.h, indicating the beginning of a new autoconfig.h file. This file does not have guard macros, nor does it refer to other files.

1 ./include/generated/autoconf.h" 1

So the next line of main.i means autoconf.hreturning from the kconfig.h file.

Subsequent kconfig.h does not contain any inlude files, so kconfig.h is cleared directly. Start the next command line.compiler_types.h, the command line also returns, and start to enter the next line of compiler_types.h, which is also included in the command line:

 1 "././include/linux/compiler_types.h" 1 means compiler_types.h starts.

The next 59 lines include a new header file compiler_attributes.h

59 "././include/linux/compiler_types.h"

1 "./include/linux/compiler_attributes.h" 1, indicating the beginning of the header file compiler_attributes.h.

There is no valid include in the header file compiler_attributes.h, so the next line falls back to line 60 of compiler_types.h.

60 "././include/linux/compiler_types.h" 2

After that, "68 "././include/linux/compiler_types.h"" line 68 of compiler_types.h contains gcc.h, and returns to line 69.

 85 "././include/linux/compiler_types.h" indicates that the type definition appears in line 85 of compiler_types.h, and will be expanded in the .i file. Note that only the type definition will be expanded, and the macro definition will not be expanded.

Finally, compiler_types.h ends, returns to the top level, and starts parsing the included files in main.c:

Comparing the definition of flags in the document, it is found that 1 and 2 are the most in main.i, 3 and 4 are few, and 1 and 2 are understandable because they represent the beginning and end return of the containment relationship respectively, and 4 means that the follow-up is treated as C External links, and 3 means system header files, no warning.

Throughout the text, find 1 place with 3, and 4 signs:

The reference place of stdargs.h is in kernel.h

 /usr/lib/gcc/x86_64-linux-gnu/11/include/stdarg.h is located in the compiler system header file directory, but in the kernel build configuration, the system header file has been shielded with -nostdinc, why is it here? Can I quote it? The kernel is set to nostdinc when compiling, that is, it does not contain system header files, but there is an exception. This exception is the stargs.h header file directory, which is specified by the -isystem macro.

So far, doubts have been explained.

Configure-isystem is set in the top-level Makefile:

References

Preprocessor Output (The C Preprocessor)

Finish

Guess you like

Origin blog.csdn.net/tugouxp/article/details/129834700