C Primer Plus (fifth edition) study notes-variable macros: ... and __VA_ARGS__, primer__va_args_
First, __VA_ARGS__
The parameters of the printf () output functions mentioned in P454 are variable. When debugging a program, you may want to define the parameters as variable output functions.
Then variadic macros are an option, for example:
#define DEBUG (X, ...) printf ("Message", #X, ":" __VA_ARGS__)
Among them, ... indicates that the parameters are variable, and __VA_ARGS__ is replaced by the actual parameter set in the preprocessing.
//variadic.c----variable macro
#define DBG (format, ...) printf ("Message" #format ": File:% s, Line:% d, Function:% s" __VA_ARGS __, __ FILE__, __LINE__, __FUNCTION__)
int main (void)
{
double x = 48;
double y = 0;
y = sqrt (x);
DBG (1, "x =% g \ r \ n", x);
DBG (2, "x =%. 2f, y =%. 4f \ r \ n", x, y);
return 0;
}
Second, if some do not support __VA_ARGS__, you can use the following method
#define DEBUG_BUFFER_MAX_LENGTH 1024
void printDebugMsg (const char * format, ...)
{
char buffer [DEBUG_BUFFER_MAX_LENGTH + 1] = {0};
va_list arg;
va_start (arg, format);
vsnprintf (buffer, DEBUG_BUFFER_MAX_LENGTH, format, arg);
va_end (arg);
printf ("% s", buffer);
}
int main (void)
{
double x = 48;
double y = 0;
y = sqrt (x);
printDebugMsg ("x =% g \ r \ n", x);
printDebugMsg ("x =%. 2f, y =%. 4f \ r \ n", x, y);
return 0;
}
Third, variable parameters (P487)
int SqSum (int n1, ...)
{
va_list arg_ptr;
int nSqsum = 0;
int n = n1;
va_start (arg_ptr, n1);
while (n> 1)
{
nSqsum + = (n * n);
n = va_arg (arg_ptr, int);
}
va_end (arg_ptr);
return nSqsum;
}
int main (void)
{
int nSqSum = SqSum (2,3,4,5, -1);
printf ("sqsum =% d \ r \ n", nSqSum);
return 0;
}
int SqSum (int n1, ...) parameters can be divided into two parts: a fixed number of fixed parameters and a variable number of optional parameters. A function requires at least one fixed parameter. The declaration of a fixed parameter is the same as an ordinary function; due to the uncertain number of optional parameters, "..." is used for declaration. Fixed parameters and optional parameters together form the parameter list of a function.
Analyze the above routine to see the role of each va_xx:
va_list arg_ptr: defines a pointer to a variable number of parameter lists;
va_start (arg_ptr, argN): Make the parameter list pointer arg_ptr point to the first optional parameter in the function parameter list. Note: argN is a fixed parameter before the first optional parameter, (or, the last fixed parameter; ... the previous parameter), the order of the parameters in the function parameter list in memory is the same as the order of the function declaration. If the declaration of a va function is void va_test (char a, char b, char c,…), then its fixed parameters are a, b, c, and the last fixed parameter argN is c, so it is va_start (arg_ptr, c ).
va_arg (arg_ptr, type): Returns the parameter pointed by the pointer arg_ptr in the parameter list, the return type is type, and the pointer arg_ptr points to the next parameter in the parameter list.
va_copy (dest, src): dest and src are both va_list. va_copy () is used to copy the parameter list pointer and initialize dest to src.
va_end (arg_ptr): clears the parameter list, and the collocated parameter pointer arg_ptr is invalid.
Explanation: After the pointer arg_ptr is invalidated, arg_ptr can be restored by calling va_start (), va_copy (). After each call to va_start () / va_copy (), there must be a corresponding va_end () to match it. The parameter pointer can move around freely in the parameter list, but it must be within va_start () ... va_end ().