Va_start and va_end, va_startva_end
To http://www.cnblogs.com/hanyonglu/archive/2011/05/07/2039916.html
This article describes how to use va_start and va_end.
Before introducing these two macros, let's take a look at the usage and principle of passing function parameters in C:
1. In C, when we cannot list the types and numbers of all real parameters passing functions, you can use the ellipsis to specify the parameter table.
Void foo (...);
Void foo (parm_list ,...); this method is not the same as we used to know before, but we should remember that this is a form of passing parameters in C and we will use it later.
2. transfer principle of function parameters
Function parameters are accessed in the form of a Data Structure: Stack, from right to left.
First, the parameter memory storage format: the parameter is stored in the stack segment of the memory, and the function is executed from the last one to the stack. Therefore, the stack bottom high address and stack Top Low address are as follows:
Void func (int x, float y, char z );
Then, when calling the function, the real parameter char z is first stack, then float y, and finally int x. Therefore, in the memory, the variable storage order is x-> y-> z, therefore, theoretically, we can find other input variables simply by detecting the address of any variable and knowing the type of other variables. The following are several major definitions in <stdarg. h>:
Typedef char * va_list;
Void va_start (va_list ap, prev_param);/* ANSI version */
Type va_arg (va_list ap, type );
Void va_end (va_list ap );
Va_list is a character pointer, which can be understood as a pointer to the current parameter. The parameter must be obtained through this pointer.
<Step 1> before calling the parameter table, define a va_list type variable (assuming that the va_list type variable is defined as ap );
<Step 2> initialize the ap and point it to the first parameter in the variable parameter table. This is achieved through va_start. The first parameter is the ap itself, the second parameter is a variable next to the variable in front of the variable table, that is, "... "The previous parameter;
<Step 3> obtain the parameter and call va_arg. The first parameter is ap, the second parameter is the specified type of the parameter to be obtained, and then the value of the specified type is returned, point the ap location to the next variable location in the variable parameter table;
<Step 4> after obtaining all the parameters, it is necessary to turn off the ap pointer to avoid danger. The method is to call va_end. The input parameter ap is set to NULL, you should turn off the pointer after obtaining the parameter table. To put it bluntly, it is to make our program robust. Generally, va_start and va_end appear in pairs. For example, int max (int n,...); the function should be implemented as follows:
# Include <iostream. h>
Void fun (int ,...)
{
Int * temp = & a; 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); // you must specify the parameter before "...".
_ Vsnprintf (pszDest, DestLen, pszFormat, args );
Va_end (args );
}
4. demonstrate how to use functions with variable parameter numbers in the ANSI standard format
# Include <stdio. h> 〉
# Include <string. h> 〉
# Include <stdarg. h> 〉
/* The function prototype Declaration requires at least one definite parameter. Note the ellipsis in brackets */
Int demo (char ,...);
Void main (void)
{
Demo ("DEMO", "This", "is", "a", "demo! ","");
}
/* ANSI standard declaration method. The ellipsis in parentheses indicates an optional parameter */
Int demo (char msg ,...)
{
/* Define the structure for saving function parameters */
Va_list argp;
Int argno = 0;
Char para;
/* Argp points to the first input optional parameter, and msg is the final parameter */
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 );
/* Set argp to NULL */
Return 0;
}
The above is an introduction to va_start and va_end.
Usage of va_start va_end
Eldest Brother, you have been cheated because you have not carefully reviewed the questions ~~~~~
For (; I & = i-1); // Note: This statement is followed by a;, that is, a closed loop
So ++ k is added after for (; j <n; ++ j,
For (; j <n; ++ j) {// here two rounds of loop, right? j = 1 and 2.
You can calculate it by yourself. This loop loops twice, so k is 2 at last.
How to Use the variable parameters, va_start, va_arg, and va_end functions in C language?
# Include <stdarg. h> // header file that must be included
Int Add (int start,...) //... is used as a placeholder
{
Va_list arg_ptr; // defines the starting pointer of the variable parameter.
Int sum = 0; // defines the sum of variable parameters
Int nArgValue = start ;//
Va_start (arg_ptr, start); // arg_ptr points to the first Variable Parameter
Do
{
Sum + = nArgValue; // sum
NArgValue = va_arg (arg_ptr, int); // arg_ptr points to the next Variable Parameter
}
While (nArgValue! = 0); // determine the end condition. The end condition is customized to 0.
Va_end (arg_ptr); // reset the pointer
Return sum;
}
The function call method is Add (,); in this way, it must end with 0, because the condition for determining the function to end with a variable parameter is to read 0 and stop.
Explanation:
Macros used:
Void va_start (va_list arg_ptr, prev_param );
Type va_arg (va_list arg_ptr, type );
Void va_end (va_list arg_ptr );
Typedef char * va_list;
# Define _ INTSIZEOF (n) (sizeof (n) + sizeof (int)-1 )&~ (Sizeof (int)-1 ))
# Define va_start (ap, v) (ap = (va_list) & v + _ INTSIZEOF (v ))
# Define va_arg (ap, t) (* (t *) (ap + = _ INTSIZEOF (t)-_ INTSIZEOF (t )))
# Define va_end (ap) (ap = (va_list) 0)
1. First, we define va_list as char *, because on our current PC, the character pointer type can be used to store memory unit addresses. On some machines, va_list is defined as void *.
2. Define _ INTSIZEOF (n) mainly for some systems that require memory alignment. This macro aims to get the actual memory size of the last fixed parameter. The sizeof operator is directly used on my machine, which has no impact on the running structure of the program. (I will see my own implementations later ).
3. va_start is defined as & v + _ INTSIZEOF (v). Here & v is the starting address of the last fixed parameter, plus the actual occupied size, the starting memory address of the first variable parameter is obtained. So after we run va_start (ap, v), the ap points to the memory address of the first variable parameter. With this address, it will be easy in the future.
Here you need to know two things:
(1) On intel + windows machines, the function stack is oriented down, and the memory address of the stack top pointer is lower than the stack bottom pointer. The rest is full.>