Today the calculation method This class feel bored extremely, so took out C + + programming way to look at. Inadvertently saw the #include<stdarg.h> va_list,va_start,va_end and other things, I do not know how to use, so I want to solve.
Back to the dorm after class, open the computer to find out the original is: defined as a variable parameter list of pointers:
Then wrote down the following a small program to use (development environment for VS2005)
#include <stdio.h>
#include <stdarg.h>
int n=5;
void Stdarg (int A1,...)
{
Va_list ARGP;
int i;
int ary[5];
Va_start (ARGP,A1);
ARY[0]=A1;
for (i=1;i<n;i++)
Ary[i]=va_arg (Argp,int);
Va_end (ARGP);
for (i=0;i<n;i++)
printf ("%d", ary[i]);
}
void Main ()
{
Stdarg (5,12,64,34,23);
}
Operation result is 5 12 64 34 23
If you want to know more about it, take a look at this article and hopefully it will help you!
In C programming we will encounter some functions with variable number of parameters, such as printf ()
This function, which is defined as this:
int printf (const char* format, ...);
In addition to having a parameter format fixed, the number and type of arguments followed are
Variable, for example, we can have the following different invocation methods:
printf ("%d", I);
printf ("%s", s);
printf ("The number is%d, string is:%s", I, s);
How to write the C function of a mutable parameter and how the function compiler for these mutable arguments are actually
Now? This article on this question to carry on some discussion, hoped can have some help to everybody. C + +
Users know that these problems do not exist in C + + because C + + is polymorphic. But C + + is a C
Hyper-Set, the following techniques can also be used in C + + programs. Limited to my level, the text if there is
Please correct me if you are not in the wrong place.
(a) write a simple variable-parameter C function
Let's explore how to write a simple variable-parameter c function. Write variable parameters
The C function uses 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 the variable-argument (variable parameter).
These macros are defined in Stdarg.h, so a program that uses mutable parameters should contain this
Header file. Let's write a simple variable parameter function, and change the function to have at least one integer
parameter, the second parameter is also an integer and is optional. The function simply prints the values of the 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%d\n", I, j);
Return
}
We can declare our function in our header file like this:
extern void Simple_va_fun (int i, ...);
We can call this in the program:
Simple_va_fun (100);
Simple_va_fun (100,200);
As you can see from the implementation of this function, we should have the following steps to use mutable parameters:
1) First define a variable of type va_list in the function, here is arg_ptr, this change
The amount 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 first
The previous parameter of a mutable parameter is a fixed parameter.
3) Then return the variable parameters with Va_arg and assign the value to the integer J. Va_arg's second
The parameter is the type of the parameter you want to return, and this is the int type.
4) Finally, the Va_end macro is used to end the variable parameter acquisition. And then you can make it in the function
With the second argument. If the function has more than one variable parameter, call Va_arg in turn
Take each parameter.
If we call it in the following three ways, it is legal, but the result is different:
1) simple_va_fun (100);
The result is: 100-123456789 (variable value)
2) Simple_va_fun (100,200);
The result is: 100 200
3) Simple_va_fun (100,200,300);
The result is: 100 200
We see that the first call has an error, the second is correct, and the third call, despite the result
Correct, but in conflict with the original design of our function. In the following section we discuss the results
The reason and how mutable parameters are handled in the compiler.
(ii) Processing of variable parameters in the compiler
We know that va_start,va_arg,va_end is defined macro in the Stdarg.h,
Because of 1) different hardware platforms 2) compilers differ, so the defined macros are also different, under
Face to VC + + in the STDARG.H x86 platform macro definition excerpt as follows (' \ ' indicates a fold line):
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)
The definition of _intsizeof (n) is primarily for some systems that require memory alignment. C-Language letter
The number is pressed from right to left onto the stack, and figure (1) is the position where the function's parameters are distributed in the stack. I
We 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, defined as &v+_intsizeof (v), while &v is a fixed parameter on the stack
Address, so after we run Va_start (AP, v), the AP points to the first mutable parameter in the heap
The address of the stack:
High Address |-----------------------------|
| function return Address |
|-----------------------------|
|....... |
|-----------------------------|
| nth parameter (first variable parameter) |
|-----------------------------|<--va_start after AP Point
| n-1 parameters (last fixed parameter) |
Low Address |-----------------------------|<--&v
Figure (1)
Then we use Va_arg () to get the variable parameter values of type T, the example of the int type, I
Let's take a look at the return value of the va_arg int:
J= (* (int*) ((AP + = _intsizeof (int))-_intsizeof (int)));
First ap+=sizeof (int), which already points to the address of the next parameter. Then return
The int* pointer to ap-sizeof (int), which is exactly the address of the first mutable parameter in the stack
(Figure 2). Then use * to get the contents of this address (parameter values) assigned to J.
High Address |-----------------------------|
| function return Address |
|-----------------------------|
|....... |
|-----------------------------|<--va_arg after AP Point
| nth parameter (first variable parameter) |
|-----------------------------|<--va_start after AP Point
| n-1 parameters (last fixed parameter) |
Low Address |-----------------------------|<--&v
Figure (2)
The last thing to say is the meaning of the Va_end macro, the x86 platform is defined as ap= (char*) 0; the AP no longer
Points to the stack, but is the same as null. Some are directly defined as ((void*) 0) so that the compiler does not
Generates code for Va_end, such as the one defined by GCC on the Linux x86 platform.
Here are a few things to note: Because the address of the parameter is used for the Va_start macro, the
A parameter cannot be declared as a register variable or as a function or an array type.
The description of Va_start, Va_arg, Va_end, that's all we have to pay attention to.
The definitions of different operating systems and hardware platforms are somewhat different, but the principles are similar.
(c) Issues to be noted in programming of variable parameters
Because Va_start, Va_arg, va_end and so on define macro, so it seems very foolish,
The type and number of variable parameters are completely controlled by the program code in the function, and it is not intelligent
To identify the number and type of different parameters.
One would ask: Is it true that the smart identification parameter is not implemented in printf? That's because the function
printf parses the type of the parameter from the fixed parameter format string, and then calls the Va_arg
To obtain a variable parameter. That is, you want to implement intelligent identification of variable parameters is to pass
To make judgments in their own programs.
There is also a problem because the compiler is not sufficiently strict about the prototype of a variable parameter function
Bad for programming errors. If Simple_va_fun () is changed to:
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\n", I, s);
Return
}
The variable parameter is char*, and when we forget to call the function with two parameters, it appears
Core dump (Unix) or invalid page error (window platform). But it's not possible.
Wrong, but the error is difficult to find, it is not conducive to us to write high-quality programs.
The following is a reference to the compatibility of VA series macros.
System V UNIX defines va_start as a macro with only one parameter:
Va_start (va_list arg_ptr);
and ANSI C is defined as:
Va_start (va_list arg_ptr, Prev_param);
If we want to use the definition of System V, we should use the Vararg.h defined in the header file.
macros, ANSI C macros are incompatible with System V macros, and we generally use ANSI C, so
The definition of ANSI C is sufficient and facilitates the porting of programs.
Summary:
The function principle of variable parameters is actually very simple, and the VA series is defined by the macro definition, the real
is now associated with the stack. When we write a variable function c function, there are pros and cons, so there's no need to
We do not need to use variable parameters. If in C + +, we should take advantage of C + + 's multi-
The ability to implement variable parameters, as far as possible to avoid the C language of the way to achieve.
#include <stdarg.h> variable parameter usage