Foreword: This article mostly refers to NetEase blogger Noisy lonely article How to implement variable parameter function and Chinaunix bo main vinge article write variable parameter C function, thanks to this two partial article detailed explanation.
Remember when you encountered a problem in a previous interview, try writing a function that is similar to the number of parameters in the printf () function. My darling, this ... I'm so ashamed. I've been looking for a job for so long that I didn't know this stuff. The result is predictable.
When we write C or C + + functions, the parameters are fixed, but in fact the number of parameters of the function is not necessarily fixed or variable,
such as the common printf and scanf functions, The number of his arguments is variable. So how do you write a function with variable parameters?
[CPP] View plain copy #include <stdio.h> # include <stdarg.h> int sum (Int first,...) /* The number of arguments is not variable, where first is called the last fixed parameter, and the second parameter is called the first variable parameter */ { int sum = 0, val = first; va_list vlist; va_start (vlist,first); while (val != 0) { sum += val; Val = va_ Arg (vlist,int); } va_end (vlist); return sum; }
When writing a variable parameter function, we need to use four macros, the four macros are:
Va_list: The type variable is used to access the variable parameter, which is actually the pointer.
Va_start (): is a macro that gets the arguments in the argument list so that the VL points to the first variable parameter, and the call to Va_end () ends after use.
Va_end: is also a macro that ends the call to Va_start ().
Va_arg: A macro that is used to obtain a value from the argument list. These four macros are defined on Linux in Stdarg.h.
Explain these four macros roughly:
1, typedef char *va_list; Defines a new type that points to a pointer to a string. The real intention is that when the pointer moves in the "1" unit, because sizeof (char) = 1; that is, the char type is a byte, the int is 4 bytes.
2, #define VA_START (ap,v) (AP = (va_list) &v + _intsizeof (v)): Va_start is defined as &v+_intsizeof (v), where &v is the last fixed parameter. The start address, plus its actual size, gets the starting memory address of the first variable parameter. So after we run Va_start (AP, v), the AP points to the memory address of the first variable parameter at the top, and with this address, the next thing is simple. The definition of _intsizeof (n) is primarily for some systems that require memory alignment. The purpose of this macro is to get the actual memory size of the last fixed parameter. Instead of using the sizeof operator directly on my machine, it has no effect on the running structure of the program.
3, #define VA_ARG (AP, T) (* (T *) ((AP) + + (_BND (_AUPBND)))-(_bnd (T,_ADNBND)))
Expand the macro to see more clearly: AP = ap + _bnd (T,_AUPBND)-------------------first specify the width of the AP's skip, pointing to the next variable parameter. * (T *) (AP-_bnd (T,_AUPBND))--Then after the AP is restored, it is converted to a "T" pointer and the value of the pointer is evaluated.
Now you can see that the macro means to find the value the current AP points to, and point the AP to the next target.
4, Va_end macro explanation: x86 platform defined as ap= (char*) 0, so that the AP no longer point to the stack, but the same as null. Some are defined directly (((void*) 0) so that the compiler does not generate code for Va_end, for example, the x86 platform for GCC on Linux is this Kind of definition. Here's a question to note: Because the address of the parameter is used for Va_start macros, the parameter cannot be declared as a register variable or as a function or array type. About Va_start, Va_arg, Va_end's description is these, we should note that the different operating systems and hardware platform definitions are somewhat different, but the principle is similar.
problems to be noticed in programming of variable parameters
because Va_start, va_arg, va_end definition macro, so it seems silly, the type and number of variable parameters are completely controlled by the program code in the function, it does not intelligently identify the number and type of different parameters. Someone would ask: So is the smart identification parameter not implemented in printf? That's because the function printf analyzes the type of the parameter from the fixed parameter format string, and then calls the va_arg to get the variable parameter. That is to say, You want to implement intelligent recognition of variable parameters is to be done in your own program to make judgments.
Also note that under Windows you can write this:
[CPP] view plain copy int sum (int first,int second ...) {int sum = 0,val = i; Va_list Vlist; Va_start (Vlist,first); ... return sum; }/* But not on Linux, because the initialization under Linux must be the last fixed parameter, in the above code first is not the last fixed parameter, so must write: * * int sum (int first,...) {int sum = 0,val = i; Va_list Vlist; Va_start (Vlist,first); ... return sum; }
Third, these macros do not provide the number of arguments to determine the actual parameters of the function, and do not provide when the end of the argument can only be controlled in the code, such as the above code to 0 for the decision to reach the end of the parameter mark, So remember that the last parameter must be 0. For more information, refer to the two-master article: http://blog.163.com/liuqiang_mail@126/blog/static/1099688752012102335624938/
Http://blog.chinaunix.net/uid-2413049-id-109789.html