Va_list is a set of macros used to solve variable parameters in C language.
He has the following members:
1) va_list variables:
# Ifdef _ m_alpha
Typedef struct {
Char * a0;/* pointer to first homed integer argument */
Int offset;/* byte offset of next parameter */
} Va_list;
# Else
Typedef char * va_list;
# Endif
2) _ intsizeof macro, obtains the length of the space occupied by the type. The minimum length is an integer multiple of the INT:
# DEFINE _ intsizeof (N) (sizeof (n) + sizeof (INT)-1 )&~ (Sizeof (INT)-1 ))
3) va_start macro to obtain the address of the first parameter in the Variable Parameter List (AP is a pointer of the va_list type and V is the leftmost parameter of the Variable Parameter ):
# Define va_start (AP, V) (AP = (va_list) & V + _ intsizeof (v ))
4) The va_arg macro gets the current parameter of the variable parameter, returns the specified type, and points the pointer to the next parameter (the t parameter describes the type of the current parameter ):
# Define va_arg (AP, t) (* (T *) (AP + = _ intsizeof (t)-_ intsizeof (t )))
5) The va_end macro clears the va_list Variable Parameter List:
# Define va_end (AP) (AP = (va_list) 0)
Usage of va_list:
(1) first define a va_list variable in the function, which is a pointer to the parameter;
(2) Use the va_start macro to initialize the va_list variable just defined;
(3) then use va_arg to return variable parameters. The second parameter of va_arg is the type of the parameter you want to return (if the function has multiple variable parameters, call va_arg in sequence to obtain parameters );
(4) use the va_end macro to end the variable parameter acquisition.
Notes for using va_list:
(1) the types and numbers of variable parameters are completely controlled by the program code. It cannot intelligently identify the numbers and types of different parameters;
(2) if we do not need to explain each parameter in detail, we only need to copy the Variable list to a buffer and use the vsprintf function;
(3) the compiler does not strictly check the prototype of the Variable Parameter function, which is not conducive to programming errors. It is not conducive to writing high-quality code;
Summary: The function principle of variable parameters is actually very simple, and the VA series are defined by Macro. Implementation is related to the stack. When we write a variable parameter C function, it has both advantages and disadvantages. In this case, we do not need to use variable parameters unless necessary. If in C ++, we should use C ++ polymorphism to implement variable parameter functions and avoid using C language as much as possible.
Specific instance:
1: When you cannot list the types and numbers of all real parameters passing functions, you can specify a parameter table with a ellipsis.
Void Foo (...);
Void
Foo (parm_list ,...);
2: transfer principle of function parameters
Function parameters are accessed in the form of Data Structure: Stack, from right to left. eg:
# Include
<Iostream>
Void fun (int ,...)
{
Int * temp =
&;
Temp ++;
For (INT I = 0; I <A; ++ I)
{
Cout <* temp
<Endl;
Temp ++;
}
}
Int main ()
{
Int A = 1;
Int B = 2;
Int c = 3;
Int d =
4;
Fun (4, A, B, C, D );
System ("pause ");
Return
0;
}
Output ::
1
2
3
4
3: Get the parameter specified by the ellipsis
Declare a va_list in the function body, and use the va_start function to obtain the parameters in the parameter list. Call va_end () to complete the use. Like this Code:
Void
Testfun (char * pszdest, int destlen, const char * pszformat ,...)
{
Va_list
ARGs;
Va_start (ARGs,
Pszformat );
_ Vsnprintf (pszdest, destlen, pszformat,
ARGs );
Va_end (ARGs );
}
4. va_start points argp to the first optional parameter. Va_arg returns the current parameter in the parameter list and points argp to the next parameter in the parameter list. Va_end clears the argp pointer to null. The function can traverse these parameters multiple times, but all parameters must start with va_start and end with va_end.
1) demonstrate how to use functions with variable parameter numbers in the ANSI standard format
# Include <stdio. h> 〉
# Include
<String. h> 〉
# Include <stdarg. h> 〉
Int demo (char ,...);
Void
Main (void)
{
Demo ("Demo", "this", "is", "A", "Demo! ",
"");
}
Int demo (char MSG ,...
)
{
Va_list
Argp;
Int argno = 0;
Char para;
Va_start (argp, MSG
);
While (1)
{
Para = va_arg (argp,
Char );
If (strcmp (para, "") = 0
)
Break;
Printf ("parameter # % d is:
% S \ n ", argno, para );
Argno ++;
}
Va_end (argp );
Return 0;
}
2) // sample code 1: use of variable parameter functions
# Include "stdio. H"
# Include "stdarg. H"
Void
Simple_va_fun (INT start ,...)
{
Va_list
Arg_ptr;
Int nargvalue = start;
Int
Nargcout = 0; // number of variable parameters
Va_start (arg_ptr, start );
// Determine the memory start address of the Variable Parameter Based on the fixed parameter address.
Do
{
++ Nargcout;
Printf ("the % d th Arg:
% D \ n ", nargcout, nargvalue );
// Output parameter values
Nargvalue =
Va_arg (arg_ptr, INT );
// Obtain the value of the next variable parameter.
} While (nargvalue! =
-1 );
Return;
}
Int main (INT argc, char * argv [])
{
Simple_va_fun (100,-1 );
Simple_va_fun (100,200,-1 );
Return 0;
}
3) // sample code 2: extension-implement simple variable parameter functions by yourself.
The following is a simple implementation of the printf function. For more information, see <The C Programming
Language> example
# Include "stdio. H"
# Include "stdlib. H"
Void
Myprintf (char * FMT ,...)
// A simple implementation similar to printf. // The parameters must be of the int type.
{
Char *
Parg = NULL;
// Equivalent to the original va_list
Char
C;
Parg = (char *)
& FMT; // do not write P = FMT
!! Because the address must be set for the // parameter, instead of the value.
Parg + =
Sizeof (FMT); // equivalent to the original va_start
Do
{
C
= * FMT;
If (C! =
'% ')
{
Putchar (C );
// Output characters as they are
}
Else
{
// Output data by formatted characters
Switch (* ++ FMT)
{
Case 'D ':
Printf ("% d", * (int *) parg ));
Break;
Case 'X ':
Printf ("% # X", * (int *) parg ));
Break;
Default:
Break;
}
Parg + =
Sizeof (INT );
// Equivalent to the original va_arg
}
++ FMT;
} While (* FMT! = '\ 0 ');
Parg =
NULL;
// Equivalent to va_end
Return;
}
Int main (INT argc, char *
Argv [])
{
Int I = 1234;
Int J =
5678;
Myprintf ("the first
Test: I = % d \ n ", I, j );
Myprintf ("The secend test: I = % d;
% X; j = % d; \ n ", I, 0 xabcd, J );
System ("pause ");
Return 0;
}