Look at the code first
Copy Code code as follows:
printf ("hello,world!"); The number of parameters is 1.
printf ("a=%d,b=%s,c=%c", a,b,c) with a number of 4 parameters.
How do I write variable parameter functions? Let's first look at how the printf function prototype is defined.
Under Linux, enter the man 3 printf, you can see the Prinf function prototype as follows:
Copy Code code as follows:
Synopsis
#include <stdio.h>
int printf (const char *format, ...);
Three points in the back ... Indicates that the number of printf parameters is variable.
How do I implement a variable parameter function?
2. Writing variable function preparation
In order to write variable parameter functions, we usually need to use the following functions defined under the <stdarg.h> header file:
Copy Code code as follows:
void Va_start (Va_list ap, last);
Type Va_arg (va_list ap, type);
void Va_end (va_list ap);
void Va_copy (va_list dest, va_list src);
which
Va_list is the data structure that holds the parameter list.
The Va_start function initializes the list of arguments based on the initialization of last.
The Va_arg function is used to remove a parameter from the argument list, which is specified by type.
The Va_copy function is used to copy the argument list.
The Va_end function performs a cleanup of the parameter list.
These functions are typically implemented with macros, such as the standard ANSI form, where the macros are defined as:
Copy Code code as follows:
typedef char * VA_LIST; String pointer
#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)
Macro _intsizeof is used to align pointers by integer byte, because the parameter stack is an integer section (pointer or value) under the C calling protocol.
The official description of the function, if you see English is annoying, you can ignore the following instructions.
Va_start ()
The Va_start () macro Initializes AP for subsequent use by Va_arg () and
Va_end (), and must be called.
The argument is the name of the last argument before the variable
Argument list, that's, the last argument of which the calling function
Knows the type.
Because the address of-argument may is used in the Va_start ()
Macro, it should not be declared as a register variable, or as a func‐
tion or an array type.
Va_arg ()
The va_arg () macro expands to a expression that has the type and value
Of the next argument in the call. The argument AP is the va_list AP
Initialized by Va_start (). Each call to VA_ARG () modifies AP so
The next call returns the next argument. The argument type is a type
Name specified so this type of a pointer to an object that has the
Specified type can is obtained simply by adding a * to type.
The Va_arg () macro after the Va_start () macro
Returns the argument after last. Successive invocations return the
Values of the remaining arguments.
If There is no next argument, or if type isn't compatible with the
Type of the actual next argument (as promoted according to the default
Argument promotions), random errors'll occur.
If AP is passed to a function that uses Va_arg (Ap,type) then the value
Of the AP is undefined on the return of this function.
Va_end ()
Each invocation of Va_start () must is matched by a corresponding invo‐
cation of Va_end () in the same function. After the call Va_end (AP) the
Variable ap is undefined. Multiple traversals of the list, each brack‐
Eted by Va_start () and va_end () are possible. Va_end () may be a macro
or a function.
One example of GNU:
Copy Code code as follows:
#include <stdio.h>
#include <stdarg.h>
void
Foo (char *fmt, ...)
{
Va_list ap;
int D;
Char c, *s;
Va_start (AP, FMT);
while (*FMT)
Switch (*fmt++) {
Case ' s ':/* String * *
s = Va_arg (AP, char *);
printf ("String%s\n", s);
Break
Case ' d ':/* int */
D = Va_arg (AP, int);
printf ("int%d\n", d);
Break
Case ' C ':/* char *
/* Need a cast here since Va_arg only takes fully promoted * *
c = (char) va_arg (AP, int);
printf ("Char%c\n", c);
Break
}
Va_end (AP);
}
Description
Va_start (AP, FMT); Used to initialize the variable argument list according to FMT.
Va_arg (AP, char *); is used to remove a parameter from the argument list, where char * is used to specify the type of the parameter being taken as a string. Each time the va_arg is invoked, the argument list AP is changed so that the next argument can be obtained next time the call is made.
Va_end (AP); Used to perform some cleanup work on the parameter list. After Va_end is called, the AP is no longer valid.
The above program gives us a way to implement the printf function, that is, by calling the Va_start function to get the parameter list, and then we take out the parameters to output.
3. Examples
For example: for printf ("a=%d,b=%s,c=%c", a,b,c) statements; FMT value is a=%d,b=%s,c=%c, the Va_start function is invoked to deposit the parameter a,b,c into the AP. Note: The% in FMT is a special character, and the argument followed by the% parameter indicates the parameter type.
So our simple printf function is as follows:
Copy Code code as follows:
#include <stdio.h>
#include <stdarg.h>
void
myprintf (char *fmt, ...)
{
Va_list ap;
int D;
Double F;
char c;
Char *s;
char flag;
Va_start (AP,FMT);
while (*FMT) {
flag=*fmt++;
if (flag!= '% ') {
Putchar (flag);
Continue
}
flag=*fmt++;//Remember to move a
Switch (flag)
{
Case ' s ':
S=va_arg (ap,char*);
printf ("%s", s);
Break
Case ' d ':/* int */
D = Va_arg (AP, int);
printf ("%d", d);
Break
Case ' F ':/* double*/
D = va_arg (ap,double);
printf ("%d", d);
Break
Case ' C ':/* char*/
c = (char) va_arg (ap,int);
printf ("%c", c);
Break
Default
Putchar (flag);
Break
}
}
Va_end (AP);
}
int main () {
Char str[10]= "Linuxcode";
int i=1024;
Double f=3.1415926;
Char c= ' V ';
myprintf ("String Is:%s,int is:%d,double Is:%f,char is:%c", str,i,f,c);
}
From the above we can know the writing of variable parameter functions, we must pass in a parameter fmt, to tell our function how to determine the number of parameters. Our variable parameter function is to determine the number of function parameters by parsing this parameter ourselves.
For example, we write a sum function that implements the following function:
Copy Code code as follows:
int sum (int cnt,...) {
int sum=0;
int i;
Va_list ap;
Va_start (AP,CNT);
for (I=0;i<cnt;++i)
Sum+=va_arg (Ap,int);
Va_end (AP);
return sum;
}
To summarize, you can initialize the parameter list by Va_start (and get the exact number of parameters), and then use the Va_arg function to remove the parameters you want from the list of arguments, and then call Va_end to perform the cleanup work.