Deep understanding of the principles of include pre-Compilation

Source: Internet
Author: User

Do you know # What operations the compiler has done after a. h file is included? Do you know why static modification is required before the function is defined in the. h file? You know # ifndef ...... # Define ...... # Is endif the essence of preventing repeated header files? This article will discuss these issues and give my understanding and thoughts. You are welcome to leave a message.

1. # functions of the include command

1.1 when not to use include

 
 
  1. // A. c file
  2.  
  3. Void test_a ()
  4. {
  5. Return;
  6. }
  7.  
  8.  
  9. // File B. c
  10.  
  11. Void test_a (); // function declaration
  12.  
  13. Void test_ B ()
  14. {
  15. Test_a (); // you can use
  16. }

In fact, such a project does not need to use the include pre-compilation command.

1.2 When to use include

If there are a lot of functions in the project, follow the above practice, it must be in every. the beginning of file c lists the declarations of all functions called in this file, which is very inefficient. Once the form of a function changes, it must be changed one by one. function declaration starting with c.
Therefore, the # include pre-compiled command was created.

 
 
  1. // A. c file
  2.  
  3. Void test_a ()
  4. {
  5. Return;
  6. }
  7.  
  8. // A. H file
  9.  
  10. Void test_a ();
  11.  
  12. // File B. c
  13.  
  14. # Include "a. h" // contains the header file containing the test_a () function declaration
  15.  
  16. Void test_ B ()
  17. {
  18. Test_a ();
  19. }

1.3 # What is the effect of include?

The above code encountered # include ". h ", the entire. h files are all copied to B. c. Therefore, B. before c, B. c has been modified to the following form:

 
 
  1. // Temporary file after B. c pre-Compilation
  2.  
  3. Void test_a ();
  4.  
  5. Void test_ B ()
  6. {
  7. Test_a ();
  8. }

It can be seen that the effect obtained is the same as that when test_a () function is manually added.

# Tips # in Linux, you can use gcc-E B. c to view the effect after pre-compiling B. c.

2. Use of static keywords

2.1 What is repeated function definition?

We often encounter errors, that is, repeated definitions of variables or functions. Here, I will give an example to illustrate what is the repeated definition of a function.

 
 
  1. // A. c file
  2.  
  3. Void test ()
  4. {
  5. Return;
  6. }
  7.  
  8. // File B. c
  9.  
  10. Void test ()
  11. {
  12. Return;
  13. }

Therefore, no error will be reported during compilation, but an error will be reported during the link:

Multiple definition of 'test', because two test functions are defined in the same project.

2.2 write function implementation in. h

What will happen if function implementation is written in. h?

 
 
  1. // A. H file
  2.  
  3. Void test_a ()
  4. {
  5. Return;
  6. }
  7.  
  8. // File B. c
  9.  
  10. # Include "a. h"
  11.  
  12. Void test_ B ()
  13. {
  14. Test_a ();
  15. }

After pre-compilation, you will find that B. c is modified to the following form:

 
 
  1. // Temporary file after B. c pre-Compilation
  2.  
  3. Void test_a ()
  4. {
  5. Return;
  6. }
  7.  
  8. Void test_ B ()
  9. {
  10. Test_a ();
  11. }

Of course, there is no problem at present, and the link can be successfully compiled. However, what if there is a. h in c. c?

 
 
  1. // C. c file
  2.  
  3. # Include "a. h"
  4.  
  5. Void test_c ()
  6. {
  7. Test_a ();
  8. }

Same as above, c. c has formed the following code after pre-Compilation:

 
 
  1. // Temporary file after c. c pre-Compilation
  2.  
  3. Void test_a ()
  4. {
  5. Return;
  6. }
  7.  
  8. Void test_c ()
  9. {
  10. Test_a ();
  11. }

Then, when the linker links), an error is reported:

Multiple definition of 'test _'

Therefore, the disadvantages of writing functions in. h are exposed. However, it is often necessary to set a function as an inline function and put it in the. h file. How can we prevent the above repeated definition errors?

2.3 static keywords

In response to the above situation, the static keyword solves this problem well.

If the static modifier is used, it indicates that the function can only be used in this file. Therefore, when the same function name in different files is modified by the static modifier, no repeated definition error is returned. For example:

 
 
  1. // A. c file
  2.  
  3. Static void test ()
  4. {
  5. Return;
  6. }
  7.  
  8. Void test_a ()
  9. {
  10. Test ();
  11. }
  12.  
  13. // File B. c
  14.  
  15. Static void test ()
  16. {
  17. Return;
  18. }
  19.  
  20. Void test_ B ()
  21. {
  22. Test ();
  23. }

No error is reported during project compilation, but the test () function can only be called by functions in a. c and B. c, and cannot be called by functions in other files such as c. c.

So what is the effect of modifying the function defined in the. h file using static?

 
 
  1. // A. H file
  2.  
  3. Static void test ()
  4. {
  5. Return;
  6. }
  7.  
  8. // File B. c
  9.  
  10. # Include "a. h"
  11.  
  12. Void test_ B ()
  13. {
  14. Test ();
  15. }
  16.  
  17. // C. c file
  18.  
  19. # Include "a. h"
  20.  
  21. Void test_c ()
  22. {
  23. Test ();
  24. }

In this case, after pre-compilation, B. c and c. in the c file, because # include ". h ", so the static void test () function is defined at the beginning of the two files. Therefore, both test_ B () and test_c () call the static void test () function in their own files () function.

Therefore, the conclusion is that if you define a function in the. h file, we recommend that you add the static keyword to it. In this way, when multiple files are included, no repeated definition errors will be generated.

3. Prevent Repeated inclusion of header files

People who often write programs know that when we write. h files, we usually add

 
 
  1. #ifndef    XXX 
  2. #define   XXX  
  3. …… 
  4. #endif 

This is intended to prevent repeated inclusion of header files. What does it mean?

It is not to prevent multiple files from containing a certain header file, but to prevent a header file from being contained multiple times by the same file. The details are as follows:

 
 
  1. // A. H file
  2.  
  3. Static void test_a ()
  4. {
  5. Return;
  6. }
  7.  
  8. // File B. c
  9.  
  10. # Include "a. h"
  11.  
  12. Void test_ B ()
  13. {
  14. Test_a ();
  15. }
  16.  
  17. // C. c
  18.  
  19. # Include "a. h"
  20.  
  21. Void test_c ()
  22. {
  23. Test_a ();
  24. }

There is no problem with this, but there will be problems in this case.

 
 
  1. // A. H file
  2.  
  3. Static void test_a ()
  4. {
  5. Return;
  6. }
  7.  
  8. // B. H file
  9.  
  10. # Include "a. h"
  11.  
  12. // C. H file
  13.  
  14. # Include "a. h"
  15.  
  16. // Main. c file
  17.  
  18. # Include "B. h"
  19. # Include "c. h"
  20.  
  21. Void main ()
  22. {
  23. Test_a ();
  24. }

In this way, the problem is "accidentally", because B. h and c. h contains. h, in the pre-compiled main. the c file is displayed as follows:

 
 
  1. // Temporary file after main. c pre-Compilation
  2.  
  3. Static void test_a ()
  4. {
  5. Return;
  6. }
  7.  
  8. Static void test_a ()
  9. {
  10. Return;
  11. }
  12.  
  13. Void main ()
  14. {
  15. Test_a ();
  16. }

In the same. c file, two definitions of test_a () are displayed. Therefore, an error is returned for repeated definitions.

However, if # ifndef… is added to a. h ...... # Define ...... # Endif.

For example, the above a. h is changed:

 
 
  1. // A. h file
  2.  
  3. # Ifndef A_H
  4. # Define A_H
  5.  
  6. Static void test_a ()
  7. {
  8. Return;
  9. }
  10.  
  11. # Endif

Pre-compile to expand main. c, the following will appear:

 
 
  1. // Temporary file pre-compiled by main. c
  2.  
  3. # Ifndef A_H
  4. # Define A_H
  5.  
  6. Static void test_a ()
  7. {
  8. Return;
  9. }
  10.  
  11. # Endif
  12.  
  13. # Ifndef A_H
  14. # Define A_H
  15.  
  16. Static void test_a ()
  17. {
  18. Return;
  19. }
  20.  
  21. # Endif
  22.  
  23. Void main ()
  24. {
  25. Test_a ();
  26. }

When compiling main. c, when the second # ifndef A_H is encountered, the Section code is skipped and will not be compiled because A_H has been defined previously. Therefore, no repeated definition errors will be reported. This is # ifndef ...... # Define ...... # The essence of endif.

This article from the "three shadows" blog, please be sure to keep this source http://ticktick.blog.51cto.com/823160/596179

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.