How to implement a variable number of parameters

xiaoxiao2021-03-06  52

The number of parameters is uncertain, and the most frequently used is Printf () and scanf (). In fact, we can also achieve such functions themselves, first look at an example:

#include

#include

Int sum (int first, int special, ...)

{

INT SUM = 0, T = first;

VA_LIST VL;

VA_START (VL, FIRST);

While (t! = -1)

{

SUM = T;

T = VA_ARG (VL, INT); / / convert the current parameter to int type

}

VA_END (VL);

Return SUM;

}

Int main (int Argc, char * argv [])

{

Printf ("THE SUM IS% D / N", SUM (30, 20, 10, -1)); // - 1 is the end sign of the parameter

Return 0;

}

In the above example, a function SUM () having a number of parameters is not required. One VA_LIST type variable VL is defined in the function, which is used to access variable parameters. It is actually a pointer, then uses VA_START to point VL to the first parameter, then use VA_ARG to traverse each parameter, VA_ARG Returns parameters The current parameter in the list and the VL point to the next parameter in the parameter list. Finally, the VL pointer is NULL through VA_END. Here, va_start, va_arg, va_end is actually a macro, then how do these macros achieve their function?

A very obvious question is that since the number of parameters are not determined before the function call, there is no way to use the determined variables like a normal function when the function is defined, so the key to the problem is how to receive These uncertain parameters? First, look at the actual situation in which the function is called, when the function is called, use the stack pass parameters, take the above example, if SUM (30, 20, 10, -1) is called, then the parameters are in the stack As shown in the figure below (assuming, in the order of the right to left):

Since the parameter is already known in the stack, then if you use a pointer (VL in the program) to the first parameter (VA_START (VL, First)), because all parameters are continuously stored, the pointer can be Access to each parameter (VA_ARG (VL, INT)), which is the implementation of the implementation of the macro in the program. After understanding the above principles, you can do not use the macro, you can achieve such a function, the following program is rewritten in the above thought: #include

Int sum (int first, int special, ...)

{

INT SUM = 0, T = first;

Char * VL; / / Define a pointer

VL = (char *) & dimst; // makes the pointer point to the first parameter

While (* VL! = -1) // - 1 is a predetermined end conver

{

SUM = * (int *) VL; // Type conversion

VL = sizeOf (int); / / Move pointer to make the pointer point down one parameter

}

Return SUM;

}

Int main (int Argc, char * argv [])

{

Printf ("THE SUM IS% D / N", SUM (30, 20, 10, -1)); // - 1 is the parameter end sign Return 0;

}

It can be seen that by using a pointer to implement the number of parameters, there is a problem in the program, that is, the mobile pointer, in the program, because the parameters I use are the same int type, so I can know in advance. When you visit the next parameter, you should move the SIZEOF (int) byte, but if the type of parameter is different? This is indeed a troublesome problem, because the number of bytes occupied by different data types may be different (such as 8 characters, the short int I 2), so it is difficult to determine how many words should be moved in advance? Festival! But the way is still, this is the use of pointers, no matter what type of pointer, it takes 4 bytes, so you can set all the passing parameters to pointers, so that you can secure 4 One byte to realize the purpose of traversing variable parameters, as for the content of the pointer and use them, of course, it is impossible to know, so this is probably like printf (), scanf () functions. The reason for a format control is also needed. FRM, ...)

{

VA_LIST VL;

VA_START (VL, FRM);

Vprintf (FRM, VL);

VA_END (VL);

}

转载请注明原文地址:https://www.9cbs.com/read-80720.html

New Post(0)