I. C LanguageSource codeThe generation phases are as follows:
C SourceProgram->Compile preprocessing->Compile->Optimization Program->Assembler->Link Program->Executable files
Where Compile and pre-process, readCSource program, the pseudo commands (#And special symbols. Or scan SourceCodeTo generate new source code for the compiler. The Preprocessing process processes the source code before the compiler.
In C
There is no internal mechanism in the language to complete the following functions: including other source files, definition macros during compilation, and determining whether to include certain code during compilation based on conditions. To do this, you need to use a Preprocessing Program. Although most compilers currently contain preprocessing programs, they are generally considered independent of compilers. Read the source code During preprocessing, check the statements and macro definitions that contain preprocessing commands, and
Converts the response of source code. The pre-processing process also deletes comments and extra spaces in the program.
2. Definition of pseudo-commands (or pre-processing commands)
The pre-processing command starts. # It must be the first character of the row except for any blank characters. # Followed by the command keyword. Any number of blank characters can exist between the keyword and. A full-line statement constitutes a preprocessing command that converts the source code before the compiler compilation. The following are some pre-processing commands:
Command usage
# Empty command, no effect
# Include contains a source code file
# Define Definition macro
# UNDEF Cancel a defined macro
# If If the given condition is true, compile the following code:
# Ifdef if the macro has been defined, compile the following code
# Ifndef if the macro is not defined, compile the following code
# Elif If the previous # If condition is not true and the current condition is true, compile the following code: Is short for else if.
# Endif End one # If ...... # Else Conditional compilation Block
# Error Stop compilation and Display error messages
Iii. Pre-processing commands mainly include the following four aspects:
1. macro definition commands
A macro defines an identifier that represents a specific content. The Preprocessing process replaces the macro identifier in the source code with the value of the macro definition. The most common usage of macros is to define the global symbols that represent a value. Second use of macros
Define a macro (macro function) with parameters. A macro can be called like a function, but it expands the macro at the call statement, replace the formal parameters in the definition with the actual parameters used for the call.
1.1 # define command
1.1.1 # define preprocessing commands are used to define macros. The simplest format of this command is: declare an identifier and give the code that this identifier represents (such as the number of circumference rates ). In the subsequent source code, we can use the defined macro to replace the code to be used, for example:
//Example 1
# DefineMax_num 10
IntArray [max_num];
For(I=0; I<Max_num; I++)
In this example, for the person who reads the program, the symbol max_num has a specific meaning. The value represents the maximum number of elements that an array can hold. This value can be used multiple times in the program. As a convention, habits alwaysDefine macros with uppercase lettersIn this way, it is easy to distinguish the macro identifier of the program from the general variable identifier. To change the array size, you only need to change the macro definition and re-compile the program.
1.1.2 The advantages of using macros are as follows:
First, it is easy to use. As follows:
//Example 2
# DefinePai 3.1415926
Pai is obviously easier to write than 3.1415926.
Second, the defined macro is meaningful and readable. For example 1, max_num, wangwen business knows that it is the maximum number, which is much more readable than simply using 10.
Third, it is easy to modify. For example, if max_num is used for dozens of times in the program, you only need to modify it once in the macro definition. Otherwise, you will change it to crash.
1.1.3 The macro value can be a constant expression that allows macro embedding (must be defined earlier ). For example:
//Example 3
# DefineOne 1
# DefineTwo 2
# DefineSum (one + two)
Note the following two points:
First, note that the macro definition above uses parentheses. Although they are not necessary. But for careful consideration, brackets should be added. For example:
Six = three * Two;
The Preprocessing process converts the previous line of code:
Six = (one + two) * Two;
Without the parentheses, convert them to six = one + two * Two.
That is to say, preprocessing is only a simple replacement of characters. Many errors may occur when you pay attention to this point.
Second, although we have used# DefineOne 1In this example, the macro definition is generally required to have its practical significance,# DefineOne 1This meaningless macro definition is not recommended. (This is probably the meaning. I forgot how to say it)
1.1.4 macros can also represent a String constant, for example:
# Define version "version 1.0 copyright (c) 2003"
1.2 # define command with parameters (macro function)
Macros with parameters seem similar to function calls. Let's look at an example:
//Example 4
# DefineCube (x) * (X)
Any numeric expression or function call can be used to replace parameter X. Here, we will remind you to pay attention to the use of parentheses. The macro extension is completely included in a pair of parentheses and the parameters are included in the brackets, which ensures the integrity of the macro and parameters. Let's look at the usage:
//Example 4 usage
IntNum=8+2;
Volume=Cube (Num );
Expanded to (8 + 2) * (8 + 2) * (8 + 2 );
If no parentheses exist, they are changed to 8 + 2*8 + 2*8 + 2.
The following usage is insecure:
Volume = cube (Num ++ );
The preceding method is understandable if cube is a function. However, because cube is a macroSide effects. The writing here is not a simple expression, they will produce unexpected results. They expand like this:
Volume = (Num ++) * (Num ++ );
Obviously, the result is 10*11*12 instead of 10*10*10;
So how can we safely use cube Macros?Operations that may cause side effects must be moved out of macro calls.:
Int num = 8 + 2;
Volume = cube (Num );
Num ++;
Improper use of macro functions may cause some difficult-to-find errors. Please use them with caution.
1.3 # Operator
The # operator that appears in the macro definition converts the parameter following it into a string. Sometimes the # In this usage is called a string operator. For example:
//Example 5
# DefinePaste (n) "adhfkj" # N
IntMain ()
{
Printf ("% S \ n", Paste (15));
Return 0;
}
//Output adhfj15
The # operator in the macro definition tells the Preprocessing Program to convert any parameter passed to the macro in the source code into a string. So the output should be adhfkj15.
1.4 ## operator (rarely used)
# Operators are used to connect parameters together. The Preprocessing Program combines the parameters on both sides of # Into a symbol. See the following example:
// Example 6
# Define Num (a, B, c) A ## B ## C
# Define STR (a, B, c) A ## B ## C
Int Main ()
{
Printf ( " % D \ n " , Num ( 1 , 2 , 3 ));
Printf ( " % S \ n " , STR ( " AA " , " Bb " , " CC " ));
Return 0 ;
}
// The output of the program is:
123
Aabbcc
2. Conditional compilation commands.
Programmers can define different macros to determine the code to be processed by the Compilation Program. The Conditional compilation command determines which codes are compiled and which ones are not compiled. You can determine the compilation conditions based on the expression value or whether a specific macro is defined.
2.1 # If/# endif/# else/# Elif command
# The if command detects the constant expression following the creation of another keyword. If the expression is true, the code after compilation will be known until # else, # Elif or # endif appears; otherwise, the compilation will not be performed.
# Endif is used to terminate # If preprocessing command.
# When the else command is used after a # If Command and the current # If command condition is not true, the code after # else is compiled.
// Example 7
# Define Debug // # Ifdef debug is true
// # Define debug 0 // This is false.
Int Main ()
{
# Ifdef debug
Printf ( " Debugging \ n " );
# Else
Printf ( " Not debugging \ n " );
# Endif
Printf ( " Running \ n " );
Return 0 ;
}
In this way, we can implement the debug function. Before outputting the debugging information, we only need to # ifdef debug to judge it once. If this is not necessary, define it in the file # define debug 0
# Elif preprocessing commands combine the functions of # else and # If commands.
// Example 8
# Define Two
Int Main ()
{
# Ifdef one
Printf ( " 1 \ n " );
# Elif Defined two
Printf ( " 2 \ n " );
# Else
Printf ( " 3 \ n " );
# Endif
}
// The output result is 2.
2.2 # ifdef and # ifndef
These two are mainly used to prevent repeated inclusion. We usually add the following section In Front Of The. h header file:
//Header file to prevent repeated inclusion
//Funca. h
# Ifndef funca_h
# DefineFunca_h
//Header file content
# EndIf
In this way, if a. h contains funca. H, B. H contains a. h, funca. H, and duplicate inclusion, errors such as type redefination may occur.
# If defined is equivalent to # ifdef; # If! Defined is equivalent to # ifndef
3. the header file contains commands.
The purpose of using header files is to make some definitions available for multiple differentCSource program usage. Because these definitions are usedCIn the source program, you only need to add one# IncludeStatement, instead of repeating the definitions in this file. The precompiled program adds all the definitions in the header file to the output file generated by the precompiled program for the Compilation Program to process it.
# The include pre-processing command is used to expand the contained files in the command. Multiple files can be included, that is, a contained file can also contain other files. The standard C compiler supports at least eight-fold nested inclusion. The Preprocessing process does not check whether a certain file is included in the conversion unit and prevents multiple inclusion of the file. The preceding solution has been provided.
The program contains header files in two formats:
# Include <my. h>
# Include "My. H"
The first method is to enclose the header file with Angle brackets. This format tells the Preprocessing Program to search for included header files in the header files of the compiler or external library. The second method is to enclose the header file with double quotation marks.
. This format tells the Preprocessing Program to search for the contained header file in the source code file of the currently compiled application. If it cannot be found, it will then search for the header file that comes with the compiler.
The reason for using two different inclusion formats is that the compiler is installed in public subdirectories, And the compiled applications are in their own private subdirectories. An application contains both the public
The header file also contains the custom private header file. Two different inclusion formats enable the compiler to differentiate a set of common header files from many header files.
4. Special symbols.
Precompiled programs can recognize some special symbols. The pre-compiled program replaces these strings with appropriate values in the source program.
4.1 _ line __
Note: It is a double underline, not a single underline. _ File _ string containing the current program file name _ line _ indicates the integer _ date _ containing the current date _ stdc _ If the compiler complies with ANSI C standard, it is a string with a non-zero value of _ time _ containing the current time.
// Example 9
# Include < Stdio. h >
Int Main ()
{
Printf ( " Hello world! \ N " );
Printf ( " % S \ n " ,__ File __);
Printf ( " % D \ n " ,__ Line __);
Return 0 ;
}
4.2 # Line
# The error command displays an error message for the compiler and stops compilation.
# The line command changes the content of _ line _ and _ file _, which are pre-defined identifiers in the Compilation Program.
# The Pragma command is not formally defined. The compiler can customize its usage. A typical usage is to disable or allow some annoying warning information.
// Example 10, # Line
# Line 100 // Initialize a row counter
# Include < Stdio. h > // Row number 100
Int Main ()
{
Printf ( " Hello world! \ N " );
Printf ( " % D " ,__ Line __);
Return 0 ;
}
// 104 output
4. The pre-compiled program basically replaces the source program. After this replacement, an output file without macro definition, Conditional compilation instructions, and special symbols is generated. The meaning of this file is the same as that of the source file without preprocessing, but the content is different. Next, the output file will be translated into machine commands as the output of the Compilation Program.