Va_list variable parameter passing

Source: Internet
Author: User


(1) write a simple variable parameter C function

Next we will discuss how to write a simple variable parameter C function.
C functions use the following Macros 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
Header file. Below we will write a simple variable parameter function. The function should have at least one integer.
Parameter. The second parameter is also an integer and is optional. The function only prints the values of these two parameters.
Void simple_va_fun (int I ,...)
{
Va_list arg_ptr;
Int j = 0;

Va_start (arg_ptr, I );
J = va_arg (arg_ptr, int );
Va_end (arg_ptr );
Printf ("% d", I, j );
Return;
}
We can declare our function in our header file as follows:
Extern void simple_va_fun (int I ,...);
We can call it in the program as follows:
Simple_va_fun (100 );
Simple_va_fun (100,200 );
From the implementation of this function, we can see that the following steps should be taken to use variable parameters:
1) first define a va_list variable in the function. Here is arg_ptr. This variable
Volume is a pointer to a parameter.
2) then use the va_start macro to initialize the variable arg_ptr. The second parameter of this macro is
The previous parameter of a variable parameter is a fixed parameter.
3) then return the variable parameter with va_arg and assign the value to the second integer j. va_arg.
The parameter is the type of the parameter you want to return. Here it is the int type.
4) use the va_end macro to end variable parameter acquisition. Then you can make
The second parameter is used. If the function has multiple variable parameters, call va_arg to obtain
Take parameters.
If we call the following three methods, they are all legal, but the results are different:
(1) simple_va_fun (100 );
Result: 100-123456789 (changed value)
(2) simple_va_fun (100,200 );
Result: 100 200
(3) simple_va_fun (100,200,300 );
Result: 100 200
We can see that there is an error in the first call, the second call is correct, and the third call despite the result
Correct, but there is a conflict with the initial design of our function. The following section describes the results.
And how variable parameters are processed in the compiler.

(2) Processing of variable parameters in the Compiler

We know that va_start, va_arg, and va_end are defined as Macros in stdarg. h,
Because 1) different hardware platforms 2) Different compilers, the defined macros are also different.
The following is an excerpt from the macro definition of the x86 Platform in stdarg. h in VC ++ ):

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)

Definition _ INTSIZEOF (n) is mainly used for some systems that require memory alignment. c letters
The number is pushed to the stack from the right to the left. Figure (1) shows the distribution position of function parameters in the stack. I
We can see that va_list is defined as char *, and some platforms or operating systems are defined as void *.
Look at the definition of va_start, which is defined as & v + _ INTSIZEOF (v), while & v is a fixed parameter in the stack
So after we run va_start (ap, v), the ap points to the first variable parameter in the heap
Stack address ,:

High address | ----------------------------- |
| Function return address |
| ----------------------------- |
| ................................ |
| ----------------------------- |
| Nth parameter (the first variable parameter) |
| ----------------------------- | <-- After va_start, the ap points
| N-1 parameter (the last fixed parameter) |
Low address | ----------------------------- | <-- & v
Figure (1)

Then, we use va_arg () to obtain the variable parameter value of type t. The above example is int type.
Let's take a look at the return value of the int type for va_arg:
J = (* (int *) (ap + = _ INTSIZEOF (int)-_ INTSIZEOF (int )));
First, ap + = sizeof (int), pointing to the address of the next parameter. Then, return
Ap-sizeof (int) int * pointer, which is the address of the first variable parameter in the stack
(Figure 2). Then, use * to get the content of this address (parameter value) and assign it to j.

High address | ----------------------------- |
| Function return address |
| ----------------------------- |
| ................................ |
| ----------------------------- | <-- Va_arg
| Nth parameter (the first variable parameter) |
| ----------------------------- | <-- After va_start, the ap points
| N-1 parameter (the last fixed parameter) |
Low address | ----------------------------- | <-- & v
Figure (2)

The last thing we want to talk about is the va_end macro. The x86 platform is defined as ap = (char *) 0, so that the ap is no longer
Point to the stack, but like NULL. Some are directly defined as (void *) 0), so the compiler does not
Code is generated for va_end. For example, gcc is defined in this way on the x86 Platform of linux.
You should pay attention to one problem here: Because the address of the parameter is used for the va_start macro
The parameter cannot be declared as a register variable or as a function or array type.
This is the description of va_start, va_arg, and va_end.
Different operating systems and hardware platforms have different definitions, but their principles are similar.

(3) Notes for variable parameters in programming

Because va_start, va_arg, and va_end are defined as macros, it seems stupid,
The type and number of variable parameters are completely controlled by the program code in this function, and cannot be intelligent.
To identify the number and type of different parameters.
Someone may ask: Isn't Intelligent Recognition parameters implemented in printf? That's because the function
Printf analyzes the parameter type from a fixed format string, and then calls va_arg
To obtain variable parameters. That is to say, if you want to intelligently identify variable parameters
Through making judgments in your own program.
Another problem is that the compiler does not strictly check the prototype of the Variable Parameter Function.
If simple_va_fun () is changed:
Void simple_va_fun (int I ,...)
{
Va_list arg_ptr;
Char * s = NULL;

Va_start (arg_ptr, I );
S = va_arg (arg_ptr, char *);
Va_end (arg_ptr );
Printf ("% d % s", I, s );
Return;
}
The variable parameter is char * type. When we forget to use two parameters to call this function
Core dump (Unix) or an invalid page error (Windows platform ).
Errors, but they are hard to find, making it difficult for us to write high-quality programs.
The following describes the compatibility of va macros.
System V Unix defines va_start as a macro with only one parameter:
Va_start (va_list arg_ptr );
Ansi c is defined:
Va_start (va_list arg_ptr, prev_param );
If we want to use the definition of system V, we should use
Macros and ansi c macros are incompatible with system V macros. We generally use ansi c, so
It is enough to use the definition of ansi c to facilitate program transplantation.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.