C/C ++ zhonghong summary CProgramOfSource codeVarious compilation commands can be included. These commands are called preprocessing commands. Although they are not actually part of the C language, they extend the C programming environment. This section describes how to use preprocessing programs and annotations to simplify the program development process and improve the readability of the program.
Macros are not part of the C/C ++ language and are pre-processed by the processor before compilation. Some functions of macros can be replaced by template, inline, and const in C ++. In my opinion, the greatest use that is retained in C ++ is automatic.CodeGenerate
The C language Preprocessing Program defined by ANSI includes the following commands:
# Define, # error, # I nclude, # If, # else, # Elif, # endif, # ifdef, # ifndef, # UNDEF, # Line, # pragma, etc. Obviously, all the pre-processing commands start with a symbol #, which is described below.
1. # define
Command # define defines an identifier and a string. Each time This identifier is encountered in the source program, it is replaced by a defined string. The ANSI standard defines the identifier as a macro name, and the replacement process is called macro replacement. The command is generally in the following format:
# Define identifier string
Note:
This statement does not have a semicolon. There can be any space between the identifier and the string. Once the string starts, it ends only with a new row.
After the macro name is defined, it can become part of other macro name definitions.
Macro replacement only replaces macro identifiers with text strings, provided that the macro identifiers must be identified independently. Otherwise, the macro identifiers are not replaced. For example:
# Define XYZ This is a test, use the macro printf ("XYZ"); // This section does not print "this is a test" and prints "XYZ ". Because the pre-compiler identifies "XYZ"
If the string is longer than one row, you can use a backslash '\' to continue the row at the end of the row.
2. # error
The processor command # error forces the Compilation Program to stop compilation, which is mainly used for program debugging.
3. # I nclude
The command # I nclude enables the compiler to embed another source file into a source file with # I nclude. The source file to be read must be enclosed by double quotation marks or angle brackets. For example:
# Include "stdio. H" or # include
Both lines of code use the C compiler to read and compile subprograms used to process Disk File libraries.
Embedding a file in the # include command is feasible. This method is called a nested embedded file. The nested hierarchy depends on the specific implementation.
If the explicit path name is part of the object identifier, search for the embedded object in only the subdirectories. Otherwise, if the file name is enclosed in double quotation marks, the current working directory is retrieved first. If no file is found, search all directories described in the command line. If no file is found, search for the standard directory defined during implementation.
If there is no explicit path name and the file name is enclosed by Angle brackets, it is first retrieved in the directory of the compiled command line.
If the file is not found, the standard directory is retrieved and the current working directory is not retrieved.
4. Conditional compilation command
There are several commands to selectively compile each part of the program's source code. This process is called Conditional compilation. Commercial software companies widely use Conditional compilation to provide and maintain many customer versions of a program.
# If, # else, # Elif and # endif
# The general meaning of IF is that if the constant expression after # If is true, the code between it and # endif will be compiled; otherwise, the code will be skipped. Command # endif identifies the end of a # If block.
# If constant-expression
Statement Sequence
# Endif
The expression following # If is evaluated during compilation. Therefore, it must contain only constants and defined identifiers and cannot use variables. The expression does not contain the operator sizeof (sizeof is also a value during compilation ).
# The else command functions a bit like the else in C; # else creates another option (in the case of # If failure ).
Note: # else belongs to the # If block.
# The Elif command has the same meaning as the else if command. It forms an if else-If step-by-step statement and supports multiple compilation options.
# Elif followed by a constant expression. If the expression is true, the code block after compilation is not tested for other # Elif expressions. Otherwise, test the next part in sequence.
# If expression
Statement Sequence
# Elif expression1
Statement Sequence
# Endif
In nested condition compilation, # endif, # else, or # Elif matches the latest # If or # Elif.
# Ifdef and # ifndef
Another method of Conditional compilation is to use the # ifdef and # ifndef commands, which respectively indicate "if there is a definition" and "if there is no definition ".
# The general form of ifdef is:
# Ifdef macroname
Statement Sequence
# Endif
# Ifdef and # ifndef can be used in # If, # else, # Elif statements, but must be used with a # endif.
5. # UNDEF
Command # UNDEF cancel the macro name defined previously. The general format is:
# UNDEF macroname
6. # Line
Command # line changes the content of _ line _ and _ file _, which are pre-defined identifiers in the Compilation Program. The basic command format is as follows:
# Line number ["FILENAME"]
The number is a positive integer, and the optional file name is any valid file identifier. The row number is the current row number in the source program, and the file name is the name of the source file. Command # Line is mainly used for debugging and other special applications.
Note: The numeric marker after # Line starts from the next row.
7. predefined macro names
The ANSI standard specifies the five predefined macro names in C. They are:
_ Line __
_ File __
_ Date __
_ Time __
_ Stdc __
If compilation is not standard, only a few of the above macro names are supported or not supported at all. Remember that the Compilation Program may also provide other predefined macro names.
The _ line _ and _ file _ macro commands have been discussed in the # Line Section. The remaining macro names are discussed here.
The _ date _ macro command contains a string in the form of month, day, or year, which indicates the date when the source file was translated to the code.
The time when the source code is translated to the target code is included in _ time _ as a string. String format: minute: second.
If the implementation is standard, macro _ stdc _ contains the decimal constant 1. If it contains any other number, the implementation is non-standard. When compiling a C ++ program, the compiler automatically defines a pre-processing name__ cplusplus. When compiling a standard C program, the compiler automatically defines the name _ stdc __.
Note: The macro name is written by an identifier and two underscores (_) on both sides.
(Some content from: http://www.bc-cn.net/Article/kfyy/cyy/jc/200511/919.html)
8. In the C and C ++ macros #,#@,##
In a macro, # is used to stringize the macro parameters following it (stringfication ), simply put, a double quotation mark is added to the left and right sides of the macro variable referenced by the macro variable.
# Is called a concatenator to connect two tokens into one. Note that the connected object is a token, not necessarily a macro variable. For example, you want to create an array composed of a menu item command name and a function pointer, and you want to have an intuitive and name relationship between the function name and the menu item command name. You can use the macro parameter # fixed part. Of course, you can also use N # symbols to connect n + 1 token. This feature is also not available for # symbols.
# @: The function is to character the macro parameters following it.
9. variable parameters in macro c...
... It is called variadic macro in macro C, that is, variable macro. For example:
# Define myprintf (templt,...) fprintf (stderr, templt ,__ va_args __)
Or # define myprintf (templt, argS...) fprintf (stderr, templt, argS)
In the first macro, the default macro _ va_args _ is used instead of the variable parameter. In the second macro, we explicitly name the variable parameter as ARGs, so we can use ARGs to represent the variable parameter in the macro definition. Like stdcall in C, the variable parameter must appear at the end of the parameter table. When the macro above can only provide the first parameter templt, the C standard requires us to write it in the form of myprintf (templt. The replacement process is myprintf ("error! \ N ",); replace with: fprintf (stderr," error! \ N ",).
This is a syntax error and cannot be compiled properly. There are two solutions to this problem. First, the solution provided by gnu cpp allows the preceding macro call to be written as: myprintf (templt), and it will be replaced with: fprintf (stderr, "error! \ N ",);
Obviously, compilation errors will still be generated here (not in this example, compilation errors will not be generated in some cases ). In addition to this method, both c99 and gnu cpp support the following macro definition methods:
# Define myprintf (templt,...) fprintf (stderr, templt, ##__ var_args __)
In this case, the # connection symbol is used to remove the comma before when _ var_args _ is empty. The translation process is as follows: myprintf (templt); is converted to: fprintf (stderr, templt );
In this way, if the templt is valid, no compilation error will be generated.
10. # Use of Pragma [reprinted]
Among all the pre-processing commands, the # pragma command may be the most complex. It is used to set the compiler status or to instruct the compiler to complete some specific actions. # The Pragma command provides a method for each compiler to provide the unique features of the host or operating system while maintaining full compatibility with C and C ++ languages. According to the definition, the compilation instructions are proprietary to machines or operating systems and are different for each compiler.
The format is generally: # pragma para, where para is a parameter. The following describes some common parameters.
(1) Message parameter. The message parameter is one of my favorite parameters. It can output relevant information in the compilation information output window, which is very important for controlling source code information. The usage is as follows:
# Pragma message ("message text ")
When the compiler encounters this instruction, it prints the message text in the compilation output window.
When we define many Macros in the program to control the source code version, we may forget whether these macros are correctly set, in this case, we can use this command to check it during compilation. Suppose we want to determine whether we have defined the _ x86 macro in the source code. The following method can be used:
# Ifdef _ x86
# Pragma message ("_ x86 macro activated! ")
# Endif
After we define the _ x86 macro, the application will display "_
X86 macro activated! ". We won't be scratching our heads because we don't remember some specific macros we defined.
(2) The other Pragma parameter that is used more frequently is code_seg. Format:
# Pragma code_seg (["section-name" [, "section-class"])
It can set the code segment where function code is stored in the program. It is used when we develop the driver.
(3) # pragma once (commonly used)
You only need to add this command at the beginning of the header file to ensure that the header file is compiled once. This command is actually available in vc6, but it is not widely used in consideration of compatibility.
(4) # pragma hdrstop indicates that the pre-compiled header file ends here, and the subsequent header files are not pre-compiled. BCB can pre-compile the header file to speed up the link, but if all header files are pre-compiled, it may occupy too much disk space. Therefore, this option is used to exclude some header files.
Sometimes there is a dependency between units. For example, unit a depends on unit B. Therefore, Unit B must be compiled before unit. You can use # pragma startup to specify the compilation priority. If # pragma package (smart_init) is used, BCB will be compiled based on the priority.
(5) # pragma resource "*. DFM" indicates adding resources in the *. DFM file to the project. *. DFM defines the form and appearance.
(6) # pragma warning (Disable: 4507 34; once: 4385; error: 164)
It is equivalent:
# Pragma warning (Disable: 4507 34) // do not display the 4507 and 34 Warnings
# Pragma warning (once: 4385) // only one warning message is reported once
# Pragma warning (error: 164) // the error message 164 is used as an error.
This pragma warning also supports the following formats:
# Pragma warning (push [, N])
# Pragma warning (POP)
Here N represents a warning level (1---4 ).
# Pragma warning (push) saves the existing warning status of all warning information.
# Pragma warning (push, n) saves the existing warning status of all warning information and sets the global warning level to n.
# Pragma warning (POP) pops up the last warning message to the stack, and all changes made between the inbound and outbound stacks are canceled. For example:
# Pragma warning (push)
# Pragma warning (Disable: 4705)
# Pragma warning (Disable: 4706)
# Pragma warning (Disable: 4707)
//.......
# Pragma warning (POP)
At the end of the Code, save all warning information (including 4707, and ). (7) Pragma comment (...)
This command puts a comment record into an object file or executable file.
Common lib keywords can help us to connect to a library file.
(8) Export DLL functions using Pragma
The traditional way to exit the DLL function is to use the module definition file (. def), Visual C ++ provides a more concise and convenient method, that is, "_ declspec ()" followed by "dllexport", telling the connection to export this function, for example:
_ Declspec (dllexport) int _ stdcall myexportfunction (INT itest );
Put "_ declspec (dllexport)" at the beginning of the function declaration, and connect the generated DLL to export the number of functions "_ myexportfunction @ 4 ".
The name of the export function above may not be what I want. We want to export the original "myexportfunction ". Fortunately, VC provides a pre-processing indicator "# pragma" to specify the connection options (not only this function, but also many indication functions), as follows:
# Pragma comment (linker, "/export: myexportfunction = _ myexportfunction @ 4 ")
This is just like the hope of the day :). If you want to specify the export sequence, or export the function as the serial number without entryname, this preprocessing indicator (specifically the connector) can be implemented. Let's take a look at the msdn syntax description:
/Export: entryname [, @ ordinal [, noname] [, Data]
@ Ordinal specifies the order. noname indicates that only the function is exported as the serial number. The data keyword specifies that the export item is a data item.
Every compilation program can use the # pragma command to activate or terminate some compilation functions supported by the Compilation Program. For example, loop optimization:
# Pragma loop_opt (on) // activate
# Pragma loop_opt (off) // terminate
Sometimes, some functions in the program will make the compiler send a warning that you are familiar with and want to ignore, such as "parameter XXX is never used in function XXX", you can do this:
# Pragma warn-100 // turn off the warning message for warning #100
Int insert_record (REC * r)
{/* Function body */}
# Pragma warn + 100 // turn the warning message for warning #100 back on
The function generates a warning message with a unique signature 100, so that the warning can be temporarily terminated.
Each compiler has different implementations for # pragma, and the effectiveness in one compiler is almost ineffective in other compilers. You can view it in the compiler documentation. Usage # pragm pack ()
# The alignment length specified by the Pragma pack. The actual use rules are as follows:
Structure, union, or data member of the class. The first one is placed in a place with the offset of 0, and the alignment of each data member is later, follow the value specified by # pragma pack and the smaller value of the member length.
That is to say, when the value of # pragma pack is equal to or greater than the length of all data members, the size of this value will not produce any effect.
The overall alignment of the structure is performed based on the smaller value between the largest data member in the structure and the value specified by # pragma pack.
Note: The use of # pragma pack (n) in the file changes the default setting and does not recover. Generally, you can use # pragma pack (push, n) and # pragma pack (POP) set and restore.
Note: The content of macro functions is discussed in another topic. The misunderstanding of macro usage has been mentioned in the text when macro is described. Finally, an example is provided, the side effect in the description refers to the impact of multiple evaluation (that is, the value) on the program when the macro expands its parameters.
Assume that a 32 B register (REG) is saved in a system. A high 16 B represents a meaning, low 16 B represents another meaning (which often appears in programs ). Now we need to separate high and low 16 B, without considering the special requirements in practice, write the code:
# Define high16bit (REG) (REG> 16)
# Define low16bit (REG) (REG <16)> 16)
This function is sufficient in most cases and will not be discussed here. This article focuses on the negative impact of this writing method. If high16bit and low16bit are not used in different statements in the program, it may be side effect, and the specific register Reg is the Status Register, the status may change at any time, so the problem is that the Status Register of high/low 16 B is not at the same time. It is difficult to find such errors in the program. Here I have relaxed the conditions. In a macro, it is even more difficult to consider the problem of multiple values of a parameter.