# Include < Stdio. h >
# Include < Stdarg. h > // To include this header file
Void Variable ( Int I ,...)
{
Int J = 0 ;
Va_list arg_ptr; // Step 2: Define the variable pointing to the parameter list
Va_start (arg_ptr, I ); // Step 2: Initialize the above variable to point it to the parameter list
While (J ! = - 1 )
{
// Step 2: Obtain the current parameter pointed to by arg_ptr. The type of this parameter is specified by the 3rd parameter of va_arg.
J = Va_arg (arg_ptr, Int );
Printf ( " % D " , J );
}
Va_end (arg_ptr ); // Step 2: Do some cleanup work
}
Main ()
{
Variable ( 3 , 3 , 4 , 5 , 6 , - 1 );
} ////////////////////////// ////////////////////////// ////////////////////////// ////// As the va_list and va_start exercises, you can learn how to use the _ vsnprintf function.
# Include < Stdio. h >
# Include < Stdarg. h >
void formatoutput ( char * Format ,...)
{< br> char S [ 10 ];
va_list arg_ptr;
va_start (arg_ptr, format);
_ vsnprintf (S, sizeof (s) - 1 , format, arg_ptr);
printf ( " % S " , s);
}
VoidMain ()
{
Formatoutput ("% S % s","D","G");
}
//////////////////// ///////////////////// Functions with an indefinite number of parameters are most frequently used: printf () and scanf (). In fact, we can also implement this function by ourselves. Example: # Include <stdio. h> # Include <stdarg. h> Int sum (INT first, int second ,...) {
Int sum = 0, T = first;
Va_list VL;
Va_start (VL, first );
While (T! =-1)
{
Sum + = T;
T = va_arg (VL, INT); // convert the current parameter to the int type
}
Va_end (VL );
Return sum;
} Int main (INT argc, char * argv [])
{
Printf ("the sum is % d \ n", sum (30, 20, 10,-1); //-1 is the parameter end flag
Return 0;
} In the preceding example, the sum () function of int type sum () is implemented for an indefinite number of parameters (). A va_list variable is defined in the function. Vl. This variable is used to access variable parameters. It is actually a pointer. Then, use va_start to point VL to the first parameter, and then use va_arg. To traverse each parameter. va_arg returns the current parameter in the parameter list and directs VL to the next parameter in the parameter list. Finally, use va_end Clear the VL pointer to null. Here, va_start, va_arg, and va_end are all macros, So how do these macros implement their functions? What about it? The obvious problem is that since the number of parameters is not determined before function calling, there is no way to define a function like a common function. In this way, fixed variables are used to accept the passed parameters. Therefore, the key to the problem is how to receive these uncertain parameters? First, read When calling a function, use the stack to pass parameters. For example, if sum (30, 20, 10, -1), as shown in the following figure (assuming that the parameters are imported to the stack from right to left ): Since the parameter in the stack has been known, if you use the pointer (ProgramTo the first parameter (va_start (VL, First), because all parameters are stored consecutively, you can move the pointer to access every parameter (va_arg (VL, INT ). That is, I used the macro Implementation ideas in the program. After understanding the above principles, you can completely ignore macros and implement such a function by yourself. The following program is based on the above Thought Rewriting: # Include <stdio. h> Int sum (INT first, int second ,...)
{
Int sum = 0, T = first;
Char * VL; // define a pointer
Vl = (char *) & first; // point the pointer to the first parameter
While (* VL! =-1) //-1 is the preset Terminator.
{
Sum + = * (int *) VL; // type conversion
Vl + = sizeof (INT); // move the pointer to point to the next Parameter
}
Return sum;
} Int main (INT argc, char * argv [])
{
Printf ("the sum is % d \ n", sum (30, 20, 10,-1); //-1 is the parameter end flag
Return 0;
}
It can be seen that the function with an indefinite number of parameters is implemented by using pointers, but there is another problem in the program: Moving the pointer In the program, because all the parameters I use are of the same int type, we can know that when accessing the next parameter, we should move sizeof (INT) Bytes, but what if the parameter type is different? This is indeed a troublesome problem, because the number of bytes occupied by different data types may be It is different (for example, the double type is 8 characters and the short int type is 2), so it is difficult to determine how many bytes should be moved in advance! However Still, this is the use of pointers. No matter what type of pointer, it occupies 4 bytes. Therefore, you can set all the parameters of the transmitter. As a pointer, You can traverse variable parameters by moving the fixed four bytes. And using them, of course, is not known in advance, so this is probably like printf (), scanf () and other functions need a format The reason for the Controller? ^_^! However, it is still a lot of trouble to implement it. For the time being, vprintf () is used to implement a function that is the same as that of printf (). Function,CodeAs follows: Void myprint (const char * frm ,...)
{
Va_list VL;
Va_start (VL, FRM );
Vprintf (FRM, VL );
Va_end (VL );
} ////////////////////// //////////////////////// The book says that when you cannot list the types and numbers of all real parameters passing functions, you can specify a parameter table with a ellipsis (...)
For example: Void Foo (...);
Void Foo (parm_list ,...);
Void Foo (...)
{
//...
}
Call: Foo (A, B, C );
I just don't understand. After passing the values of A, B, and C into the function, what variables are used to receive them ??? If it cannot be received, isn't it meaningless?
Or do not understand
Int printf (const char *...);
Printf ("Hello, & S \ n", username );
How is this c output function implemented.
Thanks first :)
Re:
First, declare a va_list in the function body, and then use the va_start function to obtain the parameters in the parameter list. after use, call va_end () to end. 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 );
}
///////////////////////////
A simple variable parameter C function
First look at the example program. This function must have at least one integer parameter, followed by a placeholder ..., The number of subsequent parameters is not fixed. In this example, all input parameters must be integers. The function only prints the values of all parameters. The function code is as follows:
// Example 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", nargcout, nargvalue); // output the value of each parameter
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;
}
The code below is explained. From the implementation of this function, we can see that using variable parameters involves the following steps: (1) because the following macros are used in the program:
Void va_start (va_list arg_ptr, prev_param );
Type va_arg (va_list arg_ptr, type );
Void va_end (va_list arg_ptr );
Va here is the meaning of Variable-argument (Variable Parameter. These macros are defined in stdarg. H, so programs that use variable parameters should include this header file. (2) The function first defines a va_list variable. Here it is arg_ptr, which is a pointer to the address of the stored parameter. the parameter value can be obtained only after obtaining the parameter address and combining the parameter type. (3) Use the va_start macro to initialize the variable arg_ptr defined in (2). The second parameter of this macro is the previous parameter in the variable parameter list, that is, the last fixed parameter. (4) use the va_arg macro in sequence to make arg_ptr return the address of the Variable Parameter. After this address is obtained, the parameter value can be obtained based on the parameter type.
The condition indicates whether the parameter value is-1. Note that the called function does not know the correct number of variable parameters when calling. The programmer must specify the end condition in the code. As for why it does not know the number of parameters, it will naturally understand after reading the internal implementation mechanisms of these macros.