Va_list is a set of macros used in variable va_start & va_arg & va_end C to solve variable parameters. The header file is from stdarg. h.
To view the Linux system source code, I usually use locate stdarg. h and find the prompt directory VI. The source file is defined as follows:
The following macro definition is also found in the tracking header file in MAC:
Typedef _ darwin_va_list va_list;
Typedef _ builtin_va_list _ darwin_va_list;/* va_list */
Essentially _ builtin_va_list
Va_list is a character pointer, which can be understood as a pointer to the current parameter. The parameter must be obtained through this pointer.
<Step 1> before calling the parameter table, you should define a va_list type variable for later use (assuming that this va_list type variable is defined as AP );
<Step 2> initialize the AP and point it to the first parameter in the variable parameter table. This is implemented through va_start. The first parameter is AP itself,
The second parameter is a variable next to the table of variable parameters;
<Step 3> obtain the parameter and call va_arg. The first parameter is AP, the second parameter is the specified type of the parameter to be obtained, and the value of this specified type is returned,
At the same time, point the AP location to the next variable location in the variable parameter table;
<Step 4> after obtaining all the parameters, we need to turn off the AP pointer to avoid danger by calling va_end. It sets the input parameter AP to null,
You should turn off the pointer after obtaining the parameter table.
Example 1:
void simple_va_fun(int i, ...){ va_list arg_ptr; va_start(arg_ptr, i); int num1 = va_arg(arg_ptr, int); int num2 = va_arg(arg_ptr, int); va_end(arg_ptr); printf("%d %d %d /n", i, num1, num2); return;}Example 2:
// Quick Information Display void show(id formatstring,...) { va_list arglist; if (!formatstring) return; va_start(arglist, formatstring); id outstring = [[[NSString alloc] initWithFormat:formatstring arguments:arglist] autorelease]; va_end(arglist); UIAlertView *av = [[[UIAlertView alloc] initWithTitle:@"LEAK DEMO" message:outstring delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil] autorelease]; [av show]; } - (void) intro { show(@"Run with Instruments using Leaks. Click a button to leak memory.%@\n",@"zyjzyj"); }
Example 3:
#define showAlert(format, ...) myShowAlert(__LINE__, (char *)__FUNCTION__, format, ##__VA_ARGS__) // Simple Alert Utility void myShowAlert(int line, char *functname, id formatstring,...) { va_list arglist; if (!formatstring) return; va_start(arglist, formatstring); id outstring = [[[NSString alloc] initWithFormat:formatstring arguments:arglist] autorelease]; va_end(arglist); NSString *filename = [[NSString stringWithCString:__FILE__ encoding:NSUTF8StringEncoding] lastPathComponent]; NSString *debugInfo = [NSString stringWithFormat:@"%@:%d\n%s", filename, line, functname]; UIAlertView *av = [[[UIAlertView alloc] initWithTitle:outstring message:debugInfo delegate:nil cancelButtonTitle:@"OK"otherButtonTitles:nil] autorelease]; [av show]; } - (void) rightAction: (id) sender { showAlert(@"You pressed the right button"); }
In C, they are defined as follows:
1) va_list variables:
# Ifdef _ m_alpha
Typedef struct {
Char * a0;/* pointer to first homed integer argument */
Int offset;/* byte offset of next parameter */
} Va_list;
# Else
Typedef char * va_list;
# Endif
2) _ intsizeof macro, obtains the length of the space occupied by the type. The minimum length is an integer multiple of the INT:
# DEFINE _ intsizeof (N) (sizeof (n) + sizeof (INT)-1 )&~ (Sizeof (INT)-1 ))
3) va_start macro to obtain the address of the first parameter in the Variable Parameter List (AP is a pointer of the va_list type and V is the leftmost parameter of the Variable Parameter ):
# Define va_start (AP, V) (AP = (va_list) & V + _ intsizeof (v ))
4) The va_arg macro gets the current parameter of the variable parameter, returns the specified type, and points the pointer to the next parameter (the t parameter describes the type of the current parameter ):
# Define va_arg (AP, t) (* (T *) (AP + = _ intsizeof (t)-_ intsizeof (t )))
5) The va_end macro clears the va_list Variable Parameter List:
# Define va_end (AP) (AP = (va_list) 0)
Further explanation:
Va_list arg_ptr: defines a pointer to a variable number of parameter lists;
Va_start (arg_ptr, argn): sets the parameter list pointer arg_ptr to the first optional parameter in the function parameter list,
Note: argn is a fixed parameter located before the first optional parameter (or, the last fixed parameter ;... ),
The order of parameters in the function parameter list in the memory is the same as that in the function declaration. If the declaration of a va function is
Void va_test (char a, char B, char C ,...), Then its fixed parameters are a, B, c in sequence, and the last fixed parameter argn is C, so it is va_start (arg_ptr, c ).
Va_arg (arg_ptr, type): return the parameter indicated by the pointer arg_ptr In the parameter list. The return type is type, and the pointer arg_ptr points to the next parameter in the parameter list.
Va_copy (DEST, Src): the types of DeST and SRC are va_list. va_copy () is used to copy the parameter list pointer and initialize DEST as SRC.
Va_end (arg_ptr): clears the parameter list. The parallel parameter pointer arg_ptr is invalid. Note: After the pointer arg_ptr is set to invalid, you can call
Va_start () and va_copy () Restore arg_ptr. Each time va_start ()/va_copy () is called, a corresponding va_end () must match it.
The parameter pointer can be freely moved back and forth in the parameter list, but must be in va_start ()... Within va_end.
The implementation of the VA function is the use and control of parameter pointers. Here, if the pointer is moved to the next parameter, what is the offset when the pointer is moved,
There is no specific answer, because memory alignment is involved here, and memory alignment is closely related to the specific hardware platform used,
For example, the well-known 32-bit x86 Platform requires that all variable addresses must be multiples of 4 (sizeof (INT) = 4 ).
In the VA mechanism, macro _ intsizeof (n) is used to solve this problem. Without these macros, VA portability is impossible.
Reference content source:
Elementary:
Http://blog.sina.com.cn/s/blog_590be5290100qhxr.html
Http://justsee.iteye.com/blog/1637173
Http://www.cnblogs.com/rainduck/archive/2010/11/10/1873417.html
Http://www.cnblogs.com/margincc/archive/2011/03/29/2095057.html#undefined
Advanced:
Http://www.cnblogs.com/diyunpeng/archive/2010/01/09/1643201.html
Http://blog.csdn.net/ritaday/article/details/6718353 (recommended)
Http://www.cocoawithlove.com/2009/05/variable-argument-lists-in-cocoa.html (English can also, strongly recommended)
Http://blog.csdn.net/skymingst/article/details/36872003 (reproduced in English, the original cannot open the connection reference)