C/C ++ compilation system Compilation Program The process is preprocessing, compilation, and linking. A Preprocessor is a program that processes program source files according to pre-processing instructions before program source files are compiled. . Preprocessor commands start with # And do not contain semicolons. The pre-processing commands are not part of the C/C ++ language and cannot be compiled and linked directly. An important function of C/C ++ is to use preprocessing commands and functions with preprocessing. The pre-processing functions provided by C/C ++ include file inclusion, macro replacement, and Conditional compilation.
1. File Inclusion
Pre-processing command # include is used to contain header files. There are two forms: # include <XXX. h> and # include "XXX. H ".
The angle brackets indicate that the included files are in the system directory. If the file to be included is not necessarily in the system directory, double quotation marks should be used.
You can specify the file path and file name in double quotation marks. If no absolute path is provided in double quotation marks, the file in the user's current directory is used by default. In this case, the system first searches for the file to be included in the user's current directory, if not, search in the system directory.
For header files compiled by the user, use double quotation marks. The header files provided by the system can be found in either angle brackets or double quotation marks. However, obviously, the angle brackets are more straightforward and more efficient.
./Indicates the current directory,.../indicates the parent directory of the current directory.
2. Macro replacement
① Macro definition
Macro definition generally uses a short name to represent a long one. Code Sequence. Macro definition includes two types: non-parameter macro definition and parameter macro definition. The code sequence represented by macro names and macro parameters can be of any meaning, such as type, constant, variable, operator, expression, statement, function, and code block. However, it is important to note that macro names and macro parameters must be valid identifiers, and the content and meaning they represent must be independent and unchanged before and after macro expansion, it cannot be explained and executed separately.
There is no macro Parameter definition. A code sequence is represented by a user-specified identifier called a macro name. This definition is generally in the form of # define identifier code sequence. The identifier after # define is called the macro definition name (macro name). Before the macro definition # define, there can be several spaces and tabs, but other characters are not allowed, macro names and code sequences are separated by space characters.
Macro Parameter definition. The macro definition with parameters further expands the non-parameter macro definition capability. At this time, the macro development not only replaces the macro name but also replaces the macro parameters. The macro definition with parameters is generally in the form of # define identifier (parameter table) code sequence. The parameters in the parameter table are separated by commas. The code sequence must contain parameters in the parameter table. When defining a macro with parameters, there is no blank character between the macro name and the left parentheses, which should be followed together; otherwise, the macro definition without parameters is changed. . The number of real parameters provided by macro calls must be the same as the number of formal parameters in the macro definition.
The valid range of a macro definition is called the scope of a macro name. The scope of a macro name ranges from the end of the macro definition to Source code End of the file. The scope of macro names is not affected by the program structure. If you need to terminate the macro name scope, you can use the preprocessing command # UNDEF to add the macro name.
Macro names are generally written in uppercase to distinguish them from variable names. If necessary, the macro name can be defined repeatedly. After the macro name is defined repeatedly, the original meaning of the macro name is replaced by the new meaning.
"" Must be paired in the macro-defined code sequence and cannot be split into strings" . For example, if # define name "vrw.art is invalid, it should be # define name" vrw.art ".
The macro definition code sequence can reference the defined macro name, that is, the macro definition can be nested.
② Multi-row macros
The macro definition must start with another line in the source file, and the line break is the end sign of the macro definition. Therefore, the macro definition ends with a line break and does not require semicolons or other symbols as separators. If the code sequence in a macro definition is too long and a row is not enough, you can continue the row. To continue a line, enter the symbol \ before entering the carriage return. Note that the carriage return must be followed by the symbol \, and other symbols cannot be inserted in the middle. Of course, the last line of the code sequence cannot end with \ . Note that multiple macro lines can be called only one row at a time. They cannot be used in expressions or as function parameters. .
③ Macro expansion
When processing macro definitions, the Preprocessor expands the macro (that is, replacing the macro ). Macro replacement first replaces all the macro names that subsequently appear in the macro definition in the source file with the code sequence they represent, if the macro contains a parameter, replace the macro parameter name in the code sequence with the macro real parameter name. Macro replacement is only used to replace the Character Sequence of the code. It does not check the syntax or perform any intermediate computation. All other operations must be completed after replacement. If the macro definition is incorrect, errors can only be found at the compilation stage after preprocessing. .
The macro name in the source code and the macro parameter name in the macro definition code sequence must be an identifier to be replaced, that is, only the identifier is replaced, and nothing else is replaced, macro or macro parameter names such as comments, string constants, and identifiers are not replaced . For example:
# Define name vrw.art, the macro name in the source code // name,/* name */, "name", and my_name_blog will not be replaced.
# Define blog (name) my_name_blog = "name", the macro parameter name in the macro definition code sequence will not be replaced.
If you want to replace the macro parameter names in the identifiers in the macro definition code sequence, you can add a connector between the macro parameter names and identifiers ##, during macro replacement, the macro parameter name and connector # Will be replaced with the macro real parameter name .# Connect macro parameter names with identifiers in the macro-defined code sequence to form a new identifier . For example:
# Define blog (name) My _ # name, blog (vr1_art) indicates my_vr1_art
# Define blog (name) Name ##_ blog, which indicates vrw.art _ blog
# Define blog (name) My _ ## name ##_ blog, blog (vr1_art) indicates my_vr1_art _ blog
If you want to replace the macro parameter name in the macro-definition code sequence with the string format of the macro parameter name (that is, double quotation marks at both ends of the macro parameter name), instead of the macro Parameter Name, you can add a symbol before the macro parameter name in the macro definition code sequence. #.# Used to convert macro parameter names into strings . For example:
# Define STR (name) # vr1_art, STR (vr1_art) indicates "vr1_art"
When the macro parameter is another macro, note that the macro parameters that are useful in the macro-definition code sequence # Or # Are not expanded. .
④ Macro independence
As mentioned in the macro definition, the content and meaning of the macro name and macro parameter name must be independent and unchanged before and after the macro development, and cannot be interpreted and executed separately. The reason is as follows: During macro calls, macro names are replaced with the code sequence defined by macro, and macro parameters are replaced with macro real parameters. After replacement, the macro-defined code sequence is naturally connected to the adjacent code in the source file, and the macro real parameter name is also naturally connected to the adjacent code in the code sequence, The code sequence defined by macros and the independence of real macro parameters do not necessarily exist. . For example:
# Define sqr (x) x * X. You want to implement the square calculation of the expression.
For macro call p = sqr (Y), you can obtain the expected macro expansion P = y * Y. However, for macro calls q = sqr (U + V), the macro expansion is Q = u + V * u + v. Obviously, the expansion result of the latter is not expected by the program designer. To maintain the independence after the macro real parameter name is replaced, brackets should be added to the form parameter in the macro definition. Furthermore, to ensure the independence of macro name calls, the macro-defined code sequence as a formula should also be enclosed in parentheses. Rewriting sqr macro definition to # define sqr (x) * (x) is the correct macro definition.
⑤ Differences between macro calls and function calls
Function calls are implemented when the program is running, while macro expansion is performed during the compilation pre-processing phase. function calls occupy the program running time, and macro calls only occupy the Compilation Time. function calls have type Requirements for real parameters, macro calls have no type concept between real parameters and macro-defined parameters, and only correspond to character sequences. A function call can return a value, and a macro call can obtain the desired code sequence. In addition, when a function is called, the real parameter expressions are evaluated independently before and the executed function is after. Macro call is a form of replacement of real parameter character sequences.
6. predefined macros
_ Date __, String constant type, indicating the compilation date of the current source file. The output format is mmm dd YYYY (for example, May 27 2006 ).
_ Time __, A String constant type, indicating the compilation date of the current source file. The output format is hh: mm: SS (for example, 09:11:10 ).
_ File __, String constant type, which indicates the name of the current source file and contains the file path.
_ Line __, an integer constant type, indicating the row number in the current source file.
_ FUNCTION __, String constant type, indicating the current function name.
These predefined macros are useful when debugging the program, because you can easily know the row where the program runs the file, which is the function.
In addition to defining macros with # define at the beginning of the source file, you can also define macros on the compiler project properties pre-processor attribute page. . This macro definition method supports numbers and strings. Generally, the format is: identifier = number or String constant. If = is omitted and the following content, the macro name identifier is an integer 1 by default. You can define macros by entering the macro definition content in the pre-processor definition attribute. Multiple macro definitions are separated by semicolons. The macro definition in the pre-processor definition must be processed before the macro definition in the source file. Its Effective Range is the entire project, unless the macro definition name is redefined in the source file or # UNDEF is specified to cancel the macro definition name, otherwise, the macro definition name remains valid in the source file.
3. Conditional compilation commands
In general, each line in the source program must be compiled during compilation, but sometimes you want to compile a part of the content only when certain conditions are met. If this condition is not met, this part of content will not be compiled. This is Conditional compilation. Conditional compilation is mainly used to select and comment out some specified code during compilation to achieve multiple version control and prevent repeated inclusion of files. # If, # ifndef, # ifdef, # else, # Elif, # endif is a common condition for compiling preprocessing commands, you can determine the compilation conditions based on the expression value or whether a specific macro is defined.
① Directive meaning
# Compile the Code if expression is non-zero;
# Ifdef compile if the macro is defined;
# Ifndef compile if the macro is not defined;
# Compile else as the remaining options of other preprocessing;
# Elif is a combination of # else and # if;
# Endif ends block control.
② Common forms
# If _ # endif format:
# If constant expression or # ifdef macro name or # ifndef macro name
Program Section
# Endif
If the constant expression is true, the macro name is defined, or the macro name is undefined, compile the program segment. Otherwise, skip this program.
# If _ # else _ # endif format:
# If constant expression or # ifdef macro name or # ifndef macro name
Procedure 1
# Else
Procedure 2
# Endif
If the constant expression is true, the macro name is defined, or the macro name is not defined, the program segment 1 after compilation; otherwise, the program segment 2 after compilation.
# If _ # Elif _ # endif format:
# If constant expression 1
Procedure 1
# Elif constant expression 2
Procedure 2
.......
# Elif constant expression n
Program section N
# Endif
Note that this form # Elif cannot be used in # ifdef and # ifndef, but # else can .
③ Expression
The pre-processor expressions include operators that involve a single number of operations (+ ,-,~ , <,>), Multiple operations (*,/, %, +,-, &, ^, |), link comparison (<, <=,>,> =, = ,! =), Macro definition judgment (defined), logical operation (! , &, |). Its priority and behavior are the same as those of the C ++ expression operator. For pre-processor expressions, remember that they are executed on the compiler Preprocessor, before compilation. .
The following table lists the priorities of operators, from top to bottom. You can use parentheses to change the priority order.
Example: # ifndef and # If! Defined has the same meaning. # ifdef and # If defined have the same meaning.
4. other pre-processing commands
In addition to the commonly used preprocessing commands discussed above, there are also three uncommon preprocessing commands: # Line, # error, and # pragma, which are described below.
① # Line
# The line command is used to reset the name and line number of the source file specified by the _ file _ and _ line _ macros.
# Line is generally in the form of # line number "FILENAME". The row number is a positive integer and the file name is optional. # Line is mainly used for debugging and other special applications, Note that the number specified after # line indicates the line number starting from the next line. .
② # Error
# The error command causes the Preprocessor to send an error message and then stop preprocessing.
# The error format is # error info, for example, # error MFC requires C ++ compilation.
③ # Pragma
# The Pragma command may be the most complex preprocessing command. It is used to set the compiler status or instruct the compiler to complete some specific actions.
# Pragma is generally in the form of # pragma para, where para is a parameter. The following describes some common parameters.
# Pragma once, you only need to add this command at the beginning of the header file to ensure that the header file is compiled once.
# Pragma message ("info"), which outputs the relevant information in the compilation information output window, for example, # pragma message ("hello ").
# Pragma warning: sets the compiler's method to process compiled warning information. For example, # pragma warning (Disable: 4507 34; once: 4385; error: 164) is equivalent to # pragma warning (Disable: 4507 34) (no warning messages 4507 and 34 are displayed), # pragma warning (once: 4385) (only one warning message is reported), # pragma warning (error: 4385) (The warning message No. 164 is used as an error ).
# Pragma comment (...), Set a comment record to the object file or executable file. A common lib annotation type is used to link a library file to the target file. The format is # pragma comment (Lib ,"*. lib "). The function is the same as that of the input library file in the" add dependency "of the Project property linker.