1) print files, functions, and program lines
In Linux, when GCC is used to compile a program, some macros are generated during GCC compilation. You can use these macros to print the information of the current source file separately. It mainly contains the current file (_ file __, which is a string char *) and the currently running function (_ FUNCTION __, which is a string char *) and the current program line (_ line __, is an integer INT ). Example:
Printf ("file: % s function: % s line: % d \ n" ,__ file __, _ functon __, _ line ); note that the above three macros are generated during compilation, rather than variables.
2) #: String Operators
In the GCC compilation system, you can use # to convert the current content to a string. For example: # define dprint (expr) printf ("<main> % s = % d \ n", # expr, expr );
Int x = 100;
Int y = 2;
Dprint (x/y );
Result: <main> x/y = 50 indicates that the # modified expression is added, which means that the parameter name in the macro is directly converted to a string.
For more information, see the following call:
Dprint (/* printf variable information */x/y );
The result is as follows: <main> x/y = 50 indicates that the compiler will not copy all the content in the macro parameter when generating a string, and the comment content will not be placed into the macro of the string, this is also because De-annotation is the content of the compiler preprocessing phase. That is to say, the annotation in the program has been removed before the actual compilation process.
Char * A = "test string"
The result of dprint (a) is as follows: <main> A = 4206930 because a is not an integer but a string pointer, the value of a is the address of variable, the content of the string is still. Let's look at it again:
Int I = 1234;
The dprint (1234) result is as follows: <main> 1234, which indicates that the compiler can convert its content to a string for the value (immediate number) written directly to the program.
As described above, the advantage of this method is that you can print the expression content in a unified way. Similarly, the following macro can be defined to print the values of other expressions:
# Define printc (expr) printf ("<char> % s = % C \ n", # expr, expr );
# Define printf (expr) printf ("<float> % s = % F \ n", # expr, expr );
# Define printd (expr) printf ("<int 16> % s = % d \ n", # expr, expr );
In the GCC compiler, two string constants can be connected to a new string. Strings are equivalent as follows:
"123456" and "123" 456"
Because # expr is essentially a string, you can directly connect it to other strings instead of using % s to print its content:
# Define printc (expr) printf ("<char>" # expr = "% C \ n", expr); others are similar.
3) ###: Join Operator
In the GCC compilation system, # Is the connection operator in the C language. It can be used to connect strings in the compilation preprocessing phase. As follows:
# Define test (x) test # x Void test1 (int) { Printf ("test1! \ N "); } Void Test2 (int) { Printf ("Test2! \ N "); }Int main (void) { Test (1 ); Test (2 ); Return 0; } The program running result is as follows: Test1 Test2 This indicates test (1), which indicates that the # Join operator converts test (1) To test1. |
In the program debugging statement, # common methods are as follows:
# Define dprint (FMT, argS ...) Printf (FMT, # ARGs)
4) The first method of macro debugging is as follows:
# Define debug_out (FMT, argS ...) \
{\
Printf ("file: % s function: % s line: % d \ n" ,__ file __, _ functon __, _ line __);\
Printf (FMT, # ARGs );\
}
In macro definition, \ is used at the end of each row to indicate that the content of the next row is continuous with the previous one. The advantage of this processing is that additional information can be printed before each line of debugging statements. After such macro processing, the debug_out method is exactly the same as that of printf, the variable parameter list and formatted output are supported, but the information of the current file, current function, and current row is appended. To call a macro method, you can add the statement end sign (;). This is like a function call, but it is not. In this case, an empty statement is added to the program. If it is not added, that's right. Macro calls are not included, right?
But there are problems or some defects. In essence, printf is a function with int return values, but it is rarely used. However, according to the definition of debug_out, it is impossible to produce a return value. In the case of a large number, this is quite common because no return value is required.
4) The second method of macro debugging is as follows:
# Define debug_out (FMT, argS ...) Printf ("file: % s function: % s line: % d" FMT, _ file __, _ functon __, _ line __, # ARGs)
This solves the problem of being unable to obtain the return value of printf. But at the same time, there is another drawback. This is because the first parameter of the printf function is in the const char * format. during use, fixed strings are often used to represent input parameters in the format. In fact, printf can also use variables as the first parameter input as follows:
Const char * s = "string ";
Printf (s );
The preceding format is valid. The output result is the string value pointed to by S. However, in the debug_out definition above, FMT must be a string and cannot use pointers. Only in this way can the string connection function be implemented. Therefore, debug_out (s) is invalid.
5) use the use_debug variable and then use ifdef use_debug to switch and control the debugging macro. In this way, you don't have to worry about removing debugging Macros in the final release. Of course, you can also define a value in use_debug. When the value is different, you can use different debugging macros based on the actual situation.
6) use do... While Definition
Using macro definition can encapsulate some short functions for ease of use. The macro format is similar to the function, but the overhead of function jump can be saved if the macro is used. Do… is often used in programs... While (0) is encapsulated into a macro. For example:
# Define Hello (STR) do {\
Printf ("Hello: % s \ n", STR );\
} While (0)