A variable parameter means that the number of parameters can vary, can be much less, also indicates that the type of the parameter can also be changed, can be int,double can be char*, class, struct and so on. Variable parameters are the key to implementing functions such as printf (),sprintf (), or you can use variable parameters to sum any number of data to make the average easier (otherwise, use an array or write an overload of each). There is a special keyword parame in C # , but there is no similar syntax in c,c++, but fortunately it provides a handler for this, and this article focuses on how to use these functions.
The first step variable parameter representation
With three points ... To represent, view the declaration of the printf () function and the scanf () function:
int printf (constChar *, ...); int scanf (constchar *, ...);
These three points are used in the macro as the variable parameter macro (Variadic Macros), and the default name is __va_args__. such as:
#define WriteLine (...) {printf (__va_args__); Putchar (' \ n ');} again WriteLine ("morewindows"); Consider the return value of printf () is the number of bytes representing the output. Change the macro above to:#define WriteLine (...) printf (__va_args__) + (Putchar (' \ n ')! = EOF? 1:0);
This allows you to get the return value of the WriteLine macro, which returns the number of bytes of output, including the last ' \ n '. both I and J will output 12 as shown in the following example .
int i = WriteLine ( " morewindows " ); WriteLine ( %d " , I); int j = printf ( " %s\n , " morewindows ); WriteLine ( %d ", j);
Second step how to handle the va_list type
Variable parameters are handled internally by Va_list and the three macros associated with it, which is the key to implementing the parameter parameters.
The definition of va_list can be found in <stdarg.h>:
typedef char * VA_LIST;
Introduce the following three macros closely related to it:Va_start (), Va_end (),and va_arg ().
The definition of these three macros can also be found in <stdarg.h>:
#define va_start (AP,V) (AP = (va_list) &v + _intsizeof (v))#define Va_end (AP) (AP = (Va_li ST) 0)#define va_arg (ap,t) ( * (t *) (AP + = _intsizeof (t))-_intsizeof (t)))
The _intsizeof macros used here are defined as follows:
#define _INTSIZEOF (N) ((sizeof (n) + sizeof (int)-1) & ~ (sizeof (int)-1))
To analyze these four macros:
The simplest of va_end (AP) is to place the pointer NULL.
va_start (ap,v) ap = (va_list) &v + _intsizeof (v) first takes v address, plus _intsizeof (v). _intsizeof (v) is a little bit more complicated. ((sizeof (n) + sizeof (int)-1) & ~ (sizeof (int)-1)) All is a bit operation, looks a bit troublesome, not really, very simple, is to take the whole to sizeof (int). For example sizeof (int) for 4,1,2,3,4 take 4,5,6,7,8 take 8. x to n rounding with c languages The arithmetic expression of is n to --will be the lowest n-1 bits clear
Va_arg (ap,t) is to remove data of type T from the AP and move the pointer back accordingly. such as Va_arg (AP, int) means to take out an int data and move the pointer four bytes.
Therefore, in the function first use va_start () to get the starting address of the variable parameter, and then use va_arg () a value, and finally with the va_end () to resolve the variable parameters.
The third step vfprintf () function and the vsprintf () function
vfprintf () This function is important, and it is known from the name that it is very much associated with the frequently used printf () function. It has more than one overloaded version, which explains one of the most common:
Function prototypes
int vfprintf
( *stream, constchar *format, va_list argptr);
The first parameter is a file pointer. file structures are necessary for reading and writing files in the C language. The incoming stdout to the screen output .
The second parameter specifies the format of the output.
The third parameter is the va_list type, which is rare, but is actually a char* representing the starting address of the variable parameter.
Return value: The number of bytes that succeeded in returning the output (not including the last ' \ ' ), which failed to return -1.
vsprintf () is similar to the above function and lists only the function prototypes:
int vsprintf ( Char *buffer, constchar *format, Va_list argptr); there is also an int _vscprintf (constchar *format, va_list argptr), which can be used to calculate vsprintf () The buffer string in the function to how many bytes of space.
code example
The following is an implementation of the printf () function (note 1) and the WriteLine () function
intPrintf (Char*Pszformat, ...) {va_list parglist; Va_start (Parglist, Pszformat); intNbytewrite =vfprintf (stdout, Pszformat, parglist); Va_end (parglist); returnNbytewrite;} intWriteLine (Char*Pszformat, ...) {va_list parglist; Va_start (Parglist, Pszformat); intNbytewrite =vfprintf (stdout, Pszformat, parglist); if(Nbytewrite! =-1) Putchar ('\ n');//NOTE 2va_end (parglist); return(Nbytewrite = =-1? -1: Nbytewrite +1);}
The call is the same as the printf () function.
Given a variable parameter to sum, unfortunately in the c,c++ can not determine the number of variable parameters passed (in printf () by scanning '% ' number to the number of actual parameters), so either to specify the number, or at the end of the parameter to set the Sentinel value:
Set Sentinel Value:
Const intGuardnumber =0;//Sentinel Logo//The number of parameter parameters can not be determined, in printf () is by scanning the '% ' number, in this by setting the Sentinel identification to determine the parameters of the parameter terminationintMySum (intI, ...) { intsum =i; Va_list argptr; Va_start (argptr, i); while((i = Va_arg (Argptr,int)) !=guardnumber) Sum+=i; Va_end (ARGPTR); returnsum;} This can be called: printf ("%d\n", MySum (1,3,5,7,9,0) , but it is not possible to directly pass in a 0:printf ("%d\n", MySum (0));//Error
Specify the number of:
intMySum (intncount, ...) { if(Ncount <=0) return 0; intsum =0; Va_list argptr; Va_start (Argptr, ncount); for(inti =0; i < ncount; i++) Sum+ = Va_arg (Argptr,int); Va_end (ARGPTR); returnsum;}
When called, the first parameter indicates the number of subsequent arguments, such as:
printf ("%d\n", MySum (513579 ) );p rintf ("%d\n", MySum (0));
Header files used by the code:
#include <stdarg.h>
#include <stdio.h>
The use of variable parameters is far more than the above, however, when using variable parameters in c,c++, you should be careful when using functions such as printf () The number of arguments passed in must not be less than the '% ' sign in the preceding format string , which would otherwise result in an access violation. Bad luck can also cause the program to crash.
The prototype of the variable parameter involves the problem of the stack of parameters when calling the function, this next time open a special discussion.
Note 1. There are no vfprintf () on the Internet to implement printf (), but few can make the function and printf () similar (actually fully familiar with printf () people have not much, do not believe the words can first look at the C Pitfalls and pitfalls learn about printf () Many less commonly used parameters, and then go to Microsoft Visual studio\vc98\crt\src to view OUTPUT. C for the implementation of printf ().
Note 2. if the output of a single character Putchar (CH) is much more efficient than printf ("%c", ch). In the case of a string that is not long, multiple calls to Putchar () will also be more efficient than calling printf ("%s\n", szstr). It is very noticeable when a function is called in large numbers.
Using variable parameters in the "Go" c,c++