Some functions in the C language use variable parameters, such as common int printf (const char * format, ...), the first parameter format is fixed, the number and type of the remaining parameters are not fixed.
C language uses VA_START and other macros to process these variable parameters. These macros look very complicated, in fact, the principle is quite simple, that is, starting the number of fixed parameters closest to the first variable parameter according to the characteristics of the parameter, and sequentially obtain the address of each variable parameter. Let's analyze these macros.
In the stdarg.h header file, there are different macro definitions for different platforms, we choose the macro definition under the X86 platform:
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)
_Intsizeof (n) macro is to consider the system that needs to be aligned, from the name of the macro should be aligned with Sizeof (int). General SizeOf (int) = 4, that is, the address of the parameter in memory is a multiple of 4. For example, if SizeOf (n) is between 1-4, then _intsizeof (n) = 4; if SizeOf (n) is between 5-8, then _intsizeof (n) = 8.
In order to obtain each variable parameter from the fixed parameters, VA_START, VA_ARG takes advantage of the following two points:
1. C language When the function is called, press the last parameter into the stack
2. The memory allocation order under the X86 platform is from the high address memory to the low address memory
High address
Nth variable parameters
. . .
Second variable parameters
First variable parameter ß ap
Fixed parameter ß v
Low address
As can be seen from the above figure, V is the address of the fixed parameter in the memory. After the VA_START is called, the AP points to the first variable parameter. The role of this macro is to increase the memory size of V on the memory address of V, which has obtained the address of the first variable parameter.
Next, it can be envisioned, if I can determine the type of variable parameter, then I know how much memory it takes, I can get the address of the next variable parameter.
Let me take a look at the VA_ARG, first AP points to the next variable parameter, then subtract the size of the current variable parameter to get the memory address of the current variable parameter, and then make a type conversion, return it.
To determine the type of each variable parameter, there are two practices, or it is the default type, or you contain enough information in the fixed parameter to make the program to determine the type of each variable parameter. For example, PrintF, the program can determine the type of each variable parameter by analyzing the Format string.
The last macro is simple, and VA_END makes the AP no longer point to the valid memory address.
After reading these macros, I can't help but let me feel again, C language is too flexible, and code can be written very simple, although sometimes it is not very clear, but once you understand, you will definitely call it. !