Compilers include: preprocessor, compiler, assembler, linker.
file.c + file.h --> preprocessor --> file.i --> compiler --> file.s --> assembler --> file.o
Precompiled:
Process all comments, replace them with spaces;
Delete all #defines and expand all macro definitions;
Handling conditional compilation directives: #if, #ifdef, #elif, #else, #endif;
Process #include, expand the included file;
Keep the #pragma that the compiler needs to use.
Examples of preprocessing directives:
gcc -E file.c -o file.i
Compile:
Perform lexical, syntactic, and semantic analysis of preprocessed files.
Lexical analysis: analyze whether keywords, identifiers, literals, etc. are legal;
Lexical analysis: analyze whether the expression follows grammatical analysis;
Semantic analysis: On the basis of syntax analysis, further analyze whether the expression is legal.
After the analysis, code optimization is performed to generate the corresponding assembly code file.
Examples of compilation directives:
gcc -S file.c -o file.s
compilation:
The assembler turns assembly code into executable instructions for the machine;
Almost every assembly statement corresponds to a machine instruction.
Example of assembly instructions:
gcc -c file.s -o file.o
Linker:
gcc file.o //Generate a.out
Linking process:
Each C language source file in the project is compiled to produce object files. How do these object files generate the final executable program?
Linker: The main function of the linker is to deal with the interaction between the various modules, so that the modules can be connected correctly.
Static linking: The content of the library is directly added to the executable program by the linker at link time:
file1.0 + file2.0 + libc.a --> linker --> a.out
The creation and use of static libraries under Linux:
Compile the static library source code: gcc -c lib.c -o lib.o Generate static library files: ar -1 lib.a lib.o Compile with static library: gcc main.c lib.a -o main.out
Dynamic link:
The executable program dynamically loads the library for linking at runtime;
The contents of the library do not go into the executable program.
lib1.so --> stub1 --> Linker linker --> a.out lib2.so --> stub2 -->
Creation and use of dynamic libraries under Linux:
Compile the dynamic library source code: gcc -shared dlib.c -o dlib.so Compile with dynamic library: gcc main.c -ldl -o main.out //-ldl compilation options: use dynamic linking
Observe the following code to experience the use of dynamic libraries:
Key system calls:
dlopen: open dynamic library file dlsym: Find the function in the dynamic library and return the calling address dlclose: close the dynamic library file
code show as below:
#include <stdio.h> #include <dlfcn.h> intmain() { void* pdlib = dlopen("./dlib.so", RTLD_LAZY); char* (*pname)(); int (*padd)(int, int); if( pdlib != NULL ) { pname = dlsym(pdlib, "name"); padd = dlsym(pdlib, "add"); if( (pname != NULL) && (padd != NULL) ) { printf("Name: %s\n", pname()); printf("Result: %d\n", padd(2, 3)); } dlclose(pdlib); } else { printf("Cannot open lib ...\n"); } return 0; }
After deleting the .so file, the .out file will not execute.
~/will$ gcc -shared dlib.c -o dlib.so ~/will$ gcc test.c -ldl -o main.out ~/will$ ./main.out Name: Dynamic Lib Result: 5
Summary: Linking refers to the final linking of the object file into an executable program;
According to the different linking methods, the linking process can be divided into:
Static link: The object file is directly linked into the executable program: (integrate the library into an application, suitable for some small programs)
Dynamic linking: Object files are loaded dynamically after the program starts.