C language parameter change problem, C Language
C ++ has the function overload method, so we can not determine the number of real parameters when calling it. In fact, C language can also be better!
In stdio. h, we can see the prototype of the printf () function:
Int printf (char * format ,...)
In fact, if we want to write such a function, we can also write it like this, so we use this symbol "... ", it is called a placeholder, and it can also be called" three points ", as long as you want! Then I can define my function as follows:
fun(int a,...){ }
This is an empty function. It does not do anything. It cannot be written just like this. How should we define it?
Let me introduce three things:
1. va_list
2. va_arg ()
3. va_start ()
During execution, the program stores the function in the memory. Now let's talk a little bit deeply about how the parameter transfer process is implemented during function storage? What is the so-called formal parameter (local variable) actually? Think about these problems and think about it. Your mind is breaking!
When calling a function, the program will also pass in real parameters and save them in the function storage area. If there are many parameters, they will be saved together.
In this case, we need to use va_list, which is a type definition. We can understand it as a pointer and point it to the address of the first parameter.
If we define it as follows: va_list pp;
Pp is a variable that points to the first parameter of all parameters. It is different from common pointer variables. It is a composite variable. What is composite variable? Struct type. If a is the first parameter, can it be written as pp =?
Suppose I have defined char d [] = "ruixin", e [] = "gelin"; can I write the value of e to d? Use strcpy (), right! Well, in the same way, we also use a function here, which is va_start ();
If it is written as follows: va_start (pp, );
Then pp points to the first parameter a, and the type int of a can be obtained.
In this case, if there is a parameter, You need to point pp to the next parameter and obtain its type. You also need to use a function. This function is: va_arg ()
You can write va_arg (pp, type) as follows, so that pp points to a parameter and you can get the type of that parameter.
Note! The type is very important. All the pointers we have learned should be clear. If the pointer type is wrong, the position is correct, and the retrieved number may be messy.
Here is a simple example:
1 # include <stdio. h> 2 # include <stdarg. h> 3 4 void fun (int ,...) 5 {6 va_list pp; 7 int n = 1; // use n to measure the number of parameters 8 va_start (pp, ); 9 do10 {11 printf ("parameter % d = % d/n", n ++, s); 12 a = va_arg (pp, int ); // point pp to the next parameter and assign the value of the next parameter to variable a13} 14 while (! = 0); // stop loop 15} 16 17 main () 18 {19 20 fun (20, 40, 60, 80, 0); 21}
Note!
The above two files must contain commands, because the three points used in the program are all in that file. Actually, it should be said that it is a function. In essence, it is just two macros.
VA_LIST is a set of macros used to solve variable parameters in C language.
Usage of VA_LIST:
(1) first define a VA_LIST variable in the function. This variable is a pointer to the parameter.
(2) then use the VA_START macro to initialize the VA_LIST variable just defined in the variable. The second parameter of this macro is the first parameter of the first variable parameter and is a fixed parameter.
(3) then use VA_ARG to return variable parameters. The second parameter of VA_ARG is the type of the parameter to be returned.
(4) use the VA_END macro to end the variable parameter acquisition. Then you can use the second parameter in the function. If a function has multiple variable parameters, call VA_ARG to obtain the parameters.
Processing of VA_LIST In the compiler:
1) after running VA_START (ap, v), the ap points to the address of the first variable parameter on the stack.
(2) VA_ARG () gets the variable parameter value of type t. In this step, apt = sizeof (t type) First, let the ap point to the address of the next parameter. Then return the t type * pointer of ap-sizeof (t type), which is the address of the first variable parameter in the stack. Then use * to get the content of this address.
(3) VA_END (). The X86 platform is defined as ap = (char *) 0), so that the ap no longer points to the stack, but is the same as NULL, some are directly defined as (void *) 0, so that the compiler will not generate code for VA_END. For example, gcc is defined in this way on the Linux X86 platform.
Note: Because the parameter address is used in the VA_START macro, the parameter cannot be declared as a register variable or as a function or array type.
Notes for using VA_LIST:
(1) Because va_start, va_arg, va_end, and so on are defined as macros, it seems stupid. the types and numbers of variable parameters are completely controlled by the program code in this function, it cannot intelligently identify the number and type of different parameters. that is to say, if you want to implement Intelligent Identification of variable parameters, you must make judgments in your own programs.
(2) another problem is that the compiler does not strictly check the prototype of the Variable Parameter Function, which is unfavorable for programming errors. It is not conducive to writing high-quality code.
Summary: The function principle of variable parameters is actually very simple, and the VA series are defined by Macro. Implementation is related to the stack. When writing a variable function's C function, it has both advantages and disadvantages. Therefore, we do not need to use variable parameters unless necessary. If in C ++, we should use C ++ polymorphism to implement variable parameter functions and avoid using C language as much as possible.
Reprinted from: http://blog.csdn.net/aking1314/article/details/5874195