#, # Operators and... in macro definition... And _ va_args _ output of custom debugging information

Source: Internet
Author: User

Output of custom debugging information
There are many methods to output debugging information, such as directly using printf or using perror or fprintf to print the information directly to the terminal when an error occurs. qdebug is generally used on QT, the daemon generally uses syslog To output debugging information to log files...
Using standard methods to print debugging information is sometimes not very convenient, such as QT programming, when debugging existing code, I want to print debugging information, print out the code location to locate the error, or add a prefix to the debugging information so that you can use grep to filter out too many debugging information, only display the debugging information of this module. In this case, you need to modify the existing qdebug one by one to make it the following form:
Qdebug ("[Module name] debugging information file: % s, line: % d", _ file __, _ line __);
Such modifications are annoying, and some unaltered ones will be omitted accidentally...
In order to conveniently manage the output of debugging information, a simple method is to define a macro for printing debugging information and then replace the original one. You can simply give a ready-made one, the following is an example. I use wifi to represent the module name of the current code. I require that all the debugging information in the module be prefixed with the pre-renewal before [WiFi, in this way, I can easily use the command line | grep "\ [WiFi \]" to filter out debugging information from other modules:
# Define qwifidebug (format ,...) qdebug ("[WiFi]" format "file: % s, line: % d, function: % s", ##__ va_args __, _ file __, _ line _, _ function __);
The preceding macro uses qdebug to output debugging information. In non-QT programs, you can change the macro to printf, And the daemon process to syslog... specifically, these macros #__ va_args __, _ file __, _ line _ and _ FUNCTION __. The following describes these macros:
1) _ va_args _ is a macro of a Variable Parameter. Few people know about this macro. The macro of this variable parameter is added in the new c99 specification, currently, only GCC is supported (not supported by the vc6.0 compiler ). # Is added before the Macro. When the number of variable parameters is 0, the # here serves to remove the redundant ",". Otherwise, compilation errors may occur, you can try.
2) _ file _ Macro will be replaced with the current source file name during pre-compilation.
3) _ line _ Macro will be replaced with the current row number during pre-compilation.
4) _ function _ macro is replaced with the current function name during pre-compilation.
With these macros, especially _ va_args _, the output of debugging information becomes more flexible.

Sometimes we want to output debugging information to the screen, and sometimes we want to output it to a file. refer to the following example:
// Debug. c
# Include <stdio. h>
# Include <string. h>
// Enable the following macro to indicate that the program is running in the debugging version; otherwise, it is the release version. It is assumed that only the debugging version outputs the debugging information.
# DEFINE _ debug
# Ifdef _ debug
// When the following macro is enabled, the debugging information is output to the file, and the comments are output to the terminal.
# Define debug_to_file
# Ifdef debug_to_file
// Output debugging information to the following file
# Define debug_file "/tmp/debugmsg"
// Buffer length of debugging information
# Define debug_buffer_max 4096
// Output debugging information to the file
# Define printdebugmsg (modulename, format ,...){\
Char buffer [debug_buffer_max + 1] = {0 };\
Snprintf (buffer, debug_buffer_max \
, "[% S]" format "file: % s, line: % d \ n", modulename, ##__ va_args __, _ file __, _ line __);\
& Nbsp; file * FD = fopen (debug_file, "");\
If (FD! = NULL ){\
Fwrite (buffer, strlen (buffer), 1, FD );\
Fflush (FD );\
Fclose (FD );\
}\
}
# Else
// Output the debugging information to the terminal
# Define printdebugmsg (modulename, format ,...)\
Printf ("[% s]" format "file: % s, line: % d \ n", modulename, ##__ va_args __, _ file __, _ line __);
# Endif // end for # ifdef debug_to_file
# Else
// Release the version and do nothing
# Define printdebugmsg (modulename, format ,...)
# Endif // end for # ifdef _ debug
Int main (INT argc, char ** argv)
{
Int DATA = 999;
Printdebugmsg ("testprogram", "Data = % d", data );
Return 0;
}

========================================================== ======================================

1 .#
If you want to include a macro parameter in a string, ansi c allows this. In the macro replacement section of the class function, # symbol is used as a preprocessing operator, which can convert the language symbol to the string. For example, if X is a macro parameter, # X can convert the parameter name into a corresponding string. This process is called stringizing ).
# Incldue <stdio. h>
# Define psqr (x) printf ("the square of" # X "is % d. \ n", (x) * (x ))
Int main (void)
{
Int y = 4;
Psqr (y );
Psqr (2 + 4 );
Return 0;
}
Output result:
The square of Y is 16.
The square of 2 + 4 is 36.
Use "Y" instead of # X for the first macro call; Use "2 + 4" generation # X for the second macro call.
2 .##
# Use a class FUNCTION macro to replace the operator. In addition, ## can be used to replace Class Object macros. This operator combines two language symbols into a single language symbol. For example:
# Define xname (n) x # N
Macro call:
Xname (4)
After expansion:
X4
Program:
# Include <stdio. h>
# Define xname (n) x # N
# Define pxn (n) printf ("X" # N "= % d \ n", X # N)
Int main (void)
{
Int xname (1) = 12; // int X1 = 12;
Pxn (1); // printf ("X1 = % d \ n", X1 );
Return 0;
}
3. Variable macros... and _ va_args __
The implementation idea is that the last parameter in the parameter list in the macro definition is the ellipsis (that is, three vertices ). In this way, the predefined macro _ va_args _ can be used in the replacement part to indicate what the ellipsis represents. For example:
# Define PR (...) printf (_ va_args __)
Pr ("hello"); --> printf ("hello ");
Pr ("Weight = % d, shipping = $. 2f", wt, SP );
--> Printf ("Weight = % d, shipping = $. 2f", wt, SP );
The ellipsis can only Replace the last macro parameter.
# Define W (x,..., Y) error!

 

========================================================== ======================================

 

1. Preprocessor glue: The # Operator

Preprocessing connector: # Operator

Like the # operator, the # operator can be used in the replacement section of a function-like macro. additionally, it can be used in the replacement section of an object-like macro. the ## operator combines two tokens into a single token.

# Connect two symbols into one.

For example, you cocould do this:

# Define xname (n) x # N

Then the macro

Xname (4)

Wocould expand to the following:

X4

Listing 1 uses this and another macro using # To do a bit of token gluing.

 

// Glue. c -- use the # Operator

# Include <stdio. h>

# Define xname (n) x # N

# Define print_xn (n) printf ("X" # N "= % d \ n", X # N );

Int main (void)

{

Int xname (1) = 14; // becomes int X1 = 14;

Int xname (2) = 20; // becomes int X2 = 20;

Print_xn (1); // becomes printf ("X1 = % d \ n", X1 );

Print_xn (2); // becomes printf ("X2 = % d \ n", X2 );

Return 0;

}

Here's the output:

X1 = 14

X2 = 20

Note how the print_xn () macro uses the # Operator to combine strings and the # Operator to combine tokens into a new identifier.

 

2. variadic macros:... and _ va_args __

Some functions, such as printf (), accept a variable number of arguments. the stdvar. h header file, provides tools for creating user-defined functions with a variable number of arguments. and c99 does the same thing for macros. although not used in the standard, the word variadic has come into currency to label this facility. (However, the process that has added stringizing and variadic to the c vocabulary has not yet led to labeling functions or macros with a fixed number of arguments as fixadic functions and normadic macros .)

The idea is that the final argument in an argument list for a macro definition can be ellipses (that is, three periods) (ellipsis ). if so, the predefined macro _ va_args _ can be used in the substitution part to indicate what will be substituted for the ellipses. for example, consider this definition:

# Define PR (...) printf (_ va_args __)

Suppose you later invoke the macro like this:

Pr ("howdy ");

Pr ("Weight = % d, shipping =$ %. 2f \ n", wt, SP );

For the first invocation, _ va_args _ expands to one argument:

"Howdy"

For the second invocation, it expands to three arguments:

"Weight = % d, shipping =$ %. 2f \ n", wt, SP

Thus, the resulting code is this:

Printf ("howdy ");

Printf ("Weight = % d, shipping =$ %. 2f \ n", wt, SP );

Listing 2 shows a slightly more ambitious example that uses String concatenation and the # Operator:

 

// Variadic. c -- variadic macros

# Include <stdio. h>

# Include <math. h>

# Define PR (x,...) printf ("message" # X ":" _ va_args __)

Int main (void)

{

Double X = 48;

Double Y;

Y = SQRT (X );

Pr (1, "x = % G \ n", X );

Pr (2, "x = %. 2f, y = %. 4f \ n", x, y );

Return 0;

}

In the first macro call, X has the value 1, so # x becomes "1". That makes the expansion look like this:

(# Add double quotation marks to parameters .)

Print ("message" "1" ":" "X = % G \ n", X );

Then the four strings are concatenated, which redirects the call to this:

Print ("Message 1: x = % G \ n", X );

Here's the output:

Message 1: x = 48

Message 2: x = 48.00, y = 6.9282

Don't forget, the ellipses have to be the last macro argument:

# Define wrong (x,..., Y) # X # _ va_args _ # Y (this is an incorrect example .)

Output of custom debugging information
There are many methods to output debugging information, such as directly using printf or using perror or fprintf to print the information directly to the terminal when an error occurs. qdebug is generally used on QT, the daemon generally uses syslog To output debugging information to log files...
Using standard methods to print debugging information is sometimes not very convenient, such as QT programming, when debugging existing code, I want to print debugging information, print out the code location to locate the error, or add a prefix to the debugging information so that you can use grep to filter out too many debugging information, only display the debugging information of this module. In this case, you need to modify the existing qdebug one by one to make it the following form:
Qdebug ("[Module name] debugging information file: % s, line: % d", _ file __, _ line __);
Such modifications are annoying, and some unaltered ones will be omitted accidentally...
In order to conveniently manage the output of debugging information, a simple method is to define a macro for printing debugging information and then replace the original one. You can simply give a ready-made one, the following is an example. I use wifi to represent the module name of the current code. I require that all the debugging information in the module be prefixed with the pre-renewal before [WiFi, in this way, I can easily use the command line | grep "\ [WiFi \]" to filter out debugging information from other modules:
# Define qwifidebug (format ,...) qdebug ("[WiFi]" format "file: % s, line: % d, function: % s", ##__ va_args __, _ file __, _ line _, _ function __);
The preceding macro uses qdebug to output debugging information. In non-QT programs, you can change the macro to printf, And the daemon process to syslog... specifically, these macros #__ va_args __, _ file __, _ line _ and _ FUNCTION __. The following describes these macros:
1) _ va_args _ is a macro of a Variable Parameter. Few people know about this macro. The macro of this variable parameter is added in the new c99 specification, currently, only GCC is supported (not supported by the vc6.0 compiler ). # Is added before the Macro. When the number of variable parameters is 0, the # here serves to remove the redundant ",". Otherwise, compilation errors may occur, you can try.
2) _ file _ Macro will be replaced with the current source file name during pre-compilation.
3) _ line _ Macro will be replaced with the current row number during pre-compilation.
4) _ function _ macro is replaced with the current function name during pre-compilation.
With these macros, especially _ va_args _, the output of debugging information becomes more flexible.

Sometimes we want to output debugging information to the screen, and sometimes we want to output it to a file. refer to the following example:
// Debug. c
# Include <stdio. h>
# Include <string. h>
// Enable the following macro to indicate that the program is running in the debugging version; otherwise, the program is released. It is assumed that only the debugging version outputs the debugging information.
# DEFINE _ debug
# Ifdef _ debug
// When the following macro is enabled, the debugging information is output to the file, and the comments are output to the terminal.
# Define debug_to_file
# Ifdef debug_to_file
// Output debugging information to the following file
# Define debug_file "/tmp/debugmsg"
// Buffer length of debugging information
# Define debug_buffer_max 4096
// Output debugging information to the file
# Define printdebugmsg (modulename, format ,...){\
Char buffer [debug_buffer_max + 1] = {0 };\
Snprintf (buffer, debug_buffer_max \
, "[% S]" format "file: % s, line: % d \ n", modulename, ##__ va_args __, _ file __, _ line __);\
& Nbsp; file * FD = fopen (debug_file, "");\
If (FD! = NULL ){\
Fwrite (buffer, strlen (buffer), 1, FD );\
Fflush (FD );\
Fclose (FD );\
}\
}
# Else
// Output the debugging information to the terminal
# Define printdebugmsg (modulename, format ,...)\
Printf ("[% s]" format "file: % s, line: % d \ n", modulename, ##__ va_args __, _ file __, _ line __);
# Endif // end for # ifdef debug_to_file
# Else
// Release the version and do nothing
# Define printdebugmsg (modulename, format ,...)
# Endif // end for # ifdef _ debug
Int main (INT argc, char ** argv)
{
Int DATA = 999;
Printdebugmsg ("testprogram", "Data = % d", data );
Return 0;
}

========================================================== ======================================

1 .#
If you want to include a macro parameter in a string, ansi c allows this. In the macro replacement section of the class function, # symbol is used as a preprocessing operator, which can convert the language symbol to the string. For example, if X is a macro parameter, # X can convert the parameter name into a corresponding string. This process is called stringizing ).
# Incldue <stdio. h>
# Define psqr (x) printf ("the square of" # X "is % d. \ n", (x) * (x ))
Int main (void)
{
Int y = 4;
Psqr (y );
Psqr (2 + 4 );
Return 0;
}
Output result:
The square of Y is 16.
The square of 2 + 4 is 36.
Use "Y" instead of # X for the first macro call; Use "2 + 4" generation # X for the second macro call.
2 .##
# Use a class FUNCTION macro to replace the operator. In addition, ## can be used to replace Class Object macros. This operator combines two language symbols into a single language symbol. For example:
# Define xname (n) x # N
Macro call:
Xname (4)
After expansion:
X4
Program:
# Include <stdio. h>
# Define xname (n) x # N
# Define pxn (n) printf ("X" # N "= % d \ n", X # N)
Int main (void)
{
Int xname (1) = 12; // int X1 = 12;
Pxn (1); // printf ("X1 = % d \ n", X1 );
Return 0;
}
3. Variable macros... and _ va_args __
The implementation idea is that the last parameter in the parameter list in the macro definition is the ellipsis (that is, three vertices ). In this way, the predefined macro _ va_args _ can be used in the replacement part to indicate what the ellipsis represents. For example:
# Define PR (...) printf (_ va_args __)
Pr ("hello"); --> printf ("hello ");
Pr ("Weight = % d, shipping = $. 2f", wt, SP );
--> Printf ("Weight = % d, shipping = $. 2f", wt, SP );
The ellipsis can only Replace the last macro parameter.
# Define W (x,..., Y) error!

 

========================================================== ======================================

 

1. Preprocessor glue: The # Operator

Preprocessing connector: # Operator

Like the # operator, the # operator can be used in the replacement section of a function-like macro. additionally, it can be used in the replacement section of an object-like macro. the ## operator combines two tokens into a single token.

# Connect two symbols into one.

For example, you cocould do this:

# Define xname (n) x # N

Then the macro

Xname (4)

Wocould expand to the following:

X4

Listing 1 uses this and another macro using # To do a bit of token gluing.

 

// Glue. c -- use the # Operator

# Include <stdio. h>

# Define xname (n) x # N

# Define print_xn (n) printf ("X" # N "= % d \ n", X # N );

Int main (void)

{

Int xname (1) = 14; // becomes int X1 = 14;

Int xname (2) = 20; // becomes int X2 = 20;

Print_xn (1); // becomes printf ("X1 = % d \ n", X1 );

Print_xn (2); // becomes printf ("X2 = % d \ n", X2 );

Return 0;

}

Here's the output:

X1 = 14

X2 = 20

Note how the print_xn () macro uses the # Operator to combine strings and the # Operator to combine tokens into a new identifier.

 

2. variadic macros:... and _ va_args __

Some functions, such as printf (), accept a variable number of arguments. the stdvar. h header file, provides tools for creating user-defined functions with a variable number of arguments. and c99 does the same thing for macros. although not used in the standard, the word variadic has come into currency to label this facility. (However, the process that has added stringizing and variadic to the c vocabulary has not yet led to labeling functions or macros with a fixed number of arguments as fixadic functions and normadic macros .)

The idea is that the final argument in an argument list for a macro definition can be ellipses (that is, three periods) (ellipsis ). if so, the predefined macro _ va_args _ can be used in the substitution part to indicate what will be substituted for the ellipses. for example, consider this definition:

# Define PR (...) printf (_ va_args __)

Suppose you later invoke the macro like this:

Pr ("howdy ");

Pr ("Weight = % d, shipping =$ %. 2f \ n", wt, SP );

For the first invocation, _ va_args _ expands to one argument:

"Howdy"

For the second invocation, it expands to three arguments:

"Weight = % d, shipping =$ %. 2f \ n", wt, SP

Thus, the resulting code is this:

Printf ("howdy ");

Printf ("Weight = % d, shipping =$ %. 2f \ n", wt, SP );

Listing 2 shows a slightly more ambitious example that uses String concatenation and the # Operator:

 

// Variadic. c -- variadic macros

# Include <stdio. h>

# Include <math. h>

# Define PR (x,...) printf ("message" # X ":" _ va_args __)

Int main (void)

{

Double X = 48;

Double Y;

Y = SQRT (X );

Pr (1, "x = % G \ n", X );

Pr (2, "x = %. 2f, y = %. 4f \ n", x, y );

Return 0;

}

In the first macro call, X has the value 1, so # x becomes "1". That makes the expansion look like this:

(# Add double quotation marks to parameters .)

Print ("message" "1" ":" "X = % G \ n", X );

Then the four strings are concatenated, which redirects the call to this:

Print ("Message 1: x = % G \ n", X );

Here's the output:

Message 1: x = 48

Message 2: x = 48.00, y = 6.9282

Don't forget, the ellipses have to be the last macro argument:

# Define wrong (x,..., Y) # X # _ va_args _ # Y (this is an incorrect example .)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.