Header file and link of C notes (2)
From the previous article, we can see that the header file is used to declare various functions or variables for calling. The function or variable ontology is supplemented in the Link phase. In main. c. We manually declare two functions, but in fact it is quite effort-consuming, because if there are many other files that need to call these two functions, we should also declare them again and again in those files; the two functions are fine. What if there are thousands or even hundreds of functions? Do I have to declare them one by one? At this time, the header file is a better choice: Just write the functions or variables that need to be used into the header file, and then include the header file. The header file is an alternative to the declaration, or a batch declaration.
The header file file1.h can be written as follows:
# Include
# Include
# Include
Extern int gen_rnd (void );
Extern void judge (int, int );
When I was writing code, I often had the following question: Can I call a function in another file? Or how can I call a function in another file? Can I call the code of another file as long as it is in the same directory? Isn't there a so-called external chain?
Now the answer is: If you want to call a function or variable in another file, first, the called function or variable must be declared as having an external link (for details, see my article on storage classes ); then declare the corresponding functions or variables (including reference header files) in this file. Finally, link the corresponding target file. In this way, we have completed the so-called cross-file call.
As I mentioned in the article about storage classes, function declarations all have external links as long as they are not declared in static mode (extern can be omitted, it must be declared outside all functions (even if it has a file scope), and modified with the keyword extern. In this way, in addition to declarations in the definition file (the definition itself is a declaration), these functions or variables will also have a corresponding declaration in all the files that reference them, these "backup" Declarations are used to tell the files that reference them: the declared functions or variables are the same function or variable and point to the same address after the link is completed. Therefore, in our example, if main. c declares the judge () function, it cannot define a function with the same name unless it decides not to link judge. o.
Next we will talk about how to find the header file and how to find the target file in the Link phase based on the header file (or declaration. # The header file after the include command is actually divided into two types, one is expanded with Angle brackets, and the other is expanded with double quotation marks. In our example, if the header file file1.h is placed in the directory where main. c is located, the command for compiling main. c is as follows:
Gcc-s main. c
Gcc will automatically search for header files in the directory where main. c is located. If file1.h is placed in a sub directory in the directory where main. c is located, the compilation command is:
Gcc-s main. c-I sub
-I option is used to specify the search path of the header file. This path is the relative path of the compiled file, and the START directory is the directory of the compiled file. Of course, this relative path can also be reflected in the # include command. For example, if # include "sub/file1.h" is used, the-I option is not required during compilation.
For header files contained in parentheses, gcc first looks for the directory specified by the-I option, and then finds the system's header file directory (usually/usr/include ); for header files enclosed by quotation marks, gcc first looks for the header files. the directory where the c file is located, then find the directory specified by-I option, and then find the system's header file directory.
The path of the specified header file is used to generate the correct declaration during compilation. if the declaration is complete, how can we find the corresponding target file? For header files written by myself, the path is provided during the link. What about header files enclosed by Angle brackets? Gcc will automatically search for the corresponding library files. For example, the printf function is in the libc library. The paths of these standard library files are fixed by the system. gcc will search for these directories by default. The default directory that the compiler will find can be viewed using the-print-search-dirs option.
So what is the difference between the library file (only the static library is considered for the moment) and the target file? In fact, we can also make judge. o and gen_rnd.o a static Library:
$ Ar rs libgame. a judge. o gen_rnd.o
The library file names start with lib, and the static library uses. a as the suffix, indicating Archive. The ar command is similar to the tar command and serves as a package. However, you can only use the ar command instead of the tar command to package the target file into a static library. Option r: Add the following file list to the package. If the package does not exist, create it. If the package already contains a file with the same name, replace it with the new one. S is used to generate a static database, which indicates creating an index for the static database. This index is used by the linker.
Then we can compile main. c:
Gcc main. c-L.-I game-o main
-L option tells the compiler where to find the required library file,-L. indicates finding in the current directory. The-l (lower-case L) Option tells the compiler to link to the libgame library. note: even if the library file is in the current directory, the compiler will not find it by default, so the-L option cannot be less.
So why should we make the target file a library file? First, if there are too many target files, the gcc command will hurt your hands (⊙, ⊙, and B), and the compilation command of the library files will be very concise. Second, suppose we are in judge again. if an unrelated add function is added to c, the irrelevant code is directly linked to the target file and added to the executable file. If there are many irrelevant functions, this means that the executable file is very large. However, if the file is linked to the library, the linker can extract only the required parts from the static library.
Finally, leave a tail: Why don't we directly include those source files such as "judge. c?