What is a variable length parameter?
A function with variable length parameters is a function that accepts variable parameters. For example, we are all very familiar
Printf, scanf, etc.
2: How to Implement the variable length parameter?
First, let's look at the following example:
# Include <stdio. h>
# Include <stdarg. h>
# Include <string. h>
Void demo (char * MSG ,...)
{
Va_list argp;
Int arg_number = 0;
Char * para = MSG;
Va_start (argp, MSG );
While (1)
{
If (strcmp (para, "/0 ")! = 0)
{
Arg_number ++;
Printf ("parameter % d is: % s/n", arg_number, para );
}
Else
Break;
Para = va_arg (argp, char *);
}
Va_end (argp );
}
Int main ()
{
Demo ("hello", "world", "/0 ");
System ("pause ");
Return 0;
}
To implement such a function, use va_list, va_start, va_arg, and va_end internally.
Macro in stdarg. h.
Va_list defines a Data Structure for saving function parameters.
Va_start (argp, MSG) points argp to the first variable parameter, and MSG is the final parameter.
The meaning of the final parameter is that all subsequent parameters are variable parameters. If the following function declaration is available
Void demo (char * msg1, char * msg2 ,...)
The final parameter here is msg2.
Va_arg (argp, char *) returns the value of the current parameter, type: char *, and points argp to the next variable-length parameter.
Number. From this step, we can see that we can use va_start and va_arg to traverse all variable-length parameters.
Va_end: Set the argp value to 0.
Let's take a look at the implementation methods of the above Macros in Visual C ++. NET 2003. First, implement va_list.
# 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
We can see that va_list is actually a machine type macro, except for Alpha machines, other machine classes
Type is defined as a char type pointer variable. The reason why it is defined as char * is that it can be used
The address is used to traverse parameters by byte.
We can see from the above that the implementation of these macros is related to machines. The following is a commonly used ix86 machine macro.
Related definitions.
# Elif defined (_ m_ix86)
# DEFINE _ intsizeof (N) (sizeof (n) + sizeof (INT)-1 )&~ (Sizeof (INT)-1 ))
# Define va_start (AP, V) (AP = (va_list) _ addressof (v) + _ intsizeof (v ))
# Define va_arg (AP, t) (* (T *) (AP + = _ intsizeof (t)-_ intsizeof (t )))
# Define va_end (AP) (AP = (va_list) 0)
# Ifdef _ cplusplus
# DEFINE _ addressof (V) (& reinterpret_cast <const char &> (v ))
# Else
# DEFINE _ addressof (V) (& (v ))
# Endif
First look at _ intsizeof (N)
We know that for ix86, sizeof (INT) must be an integer multiple of 4, SO ~ (Sizeof (INT)-1) The value must be
The right side [sizeof (N)-1]/2 digits is 0. The macro ensures that the right side [sizeof (N)-1]/2 digits are 0, and the remaining positions are
It is 1, so the value of _ intsizeof (n) can only be 2, 4, 8, 16,... and so on. In fact, it achieves byte alignment.
# Define va_start (AP, V) (AP = (va_list) _ addressof (v) + _ intsizeof (v ))
So the role of va_start (AP, v) is very clear, _ addressof (v) defines the starting address of V, _ intsizeof (v) defines the V
Memory occupied, so the AP points to the starting address of the parameter after v.
# Define va_arg (AP, t) (* (T *) (AP + = _ intsizeof (t)-_ intsizeof (t )))
AP + = _ intsizeof (t) enables the AP to point to the address of the next Parameter
(* (T *) (AP + = _ intsizeof (t)-_ intsizeof (t) returns the value of the current T type parameter.
# Define va_end (AP) (AP = (va_list) 0)
Set the value of the AP variable to 0.
Through the above analysis, we once again confirmed our interpretation of Variable Parameter implementation.
Therefore, we can summarize the general implementation methods of variable-length parameter functions:
1: declare the prototype, such as void demo (char * MSG,...). Note that the prototype Declaration of the variable length parameter must contain at least
A definite parameter.
2: Use va_list to define the data structure for saving function parameters. It can be understood as a pointer variable (which will be explained later ).
3: Use va_start to point the variable defined in the previous step to the first variable parameter.
4: Use va_arg to traverse all variable parameters.
5: Use va_end to set the address value held by the pointer variable to 0.