The implementation method of C + + variable parameters _c language

Source: Internet
Author: User
Tags garbage collection

The implementation of a variable parameter solves three problems:

1. How to invoke a function with variable parameters
2. How to compile a program with variable parameters
3. How to hold a variable parameter in a function body with variable parameters
The first problem, when invoked, is to pass in variable parameters where variable parameters can be passed in, and of course there are areas to be noted, which are mentioned later.

The second problem is that the compiler needs a loose check scheme at compile time, which can cause problems, such as bad programming errors.

The third is that I am here to care about the problem, the first to C language as an example to analyze its implementation principle.

printf and scanf are the most common variable parameter functions in the C language standard library, and printf signatures are

Copy Code code as follows:

int printf (const char* format, ...);

Among them, ... Represents a variable parameter, now imitate printf to write a simple example.

De jure a simple example:

Copy Code code as follows:

#include <windows.h>
#include <stdio.h>

void Variableargumentmethod (int argc, ...);

int main () {
Variableargumentmethod (6, 4, 7, 3, 0, 7, 9);
return 0;
}

void Variableargumentmethod (int argc, ...) {
Declares a pointer to hold a variable parameter
Va_list parg;
Initializes parg to point to the first parameter
Va_start (PARG, ARGC);
Output parameters
for (int i = 0; I!= argc; ++i) {
Gets the parameters that the PARG points to and outputs
printf ("%d,", Va_arg (parg, int));
}

Va_end (PARG);
}


void Variableargumentmethod (int argc, ...) is a variable parameter function that is used to output a variable parameter with a specified number of ARGC.
Variableargumentmethod (6, 4, 7, 3, 0, 7, 9); is a call to this function, and the first argument 6 indicates that the following 6 parameters are followed.

In the body of the Variableargumentmethod function:

1. Va_list parg;

Defines a pointer to hold a variable parameter that can hold the first variable parameter by moving the pointer through the variable parameter table passed in.

2. Va_start (PARG, ARGC);

Let Parg point to the first argument in the variable argument list. ARGC is a parameter to locate, because the variable parameter starts after argc, which explains why you are positioning this way.

3. Va_arg (parg, int);

This sentence is placed in the loop body to remove parameters from the variable parameter table. Also, it will let parg move to the next variable parameter (if it has reached the end, it will point to a meaningless address).

4. Va_end (PARG);

To parg Clear Zero, personally think here dispensable, because PARG no longer need.

In this way, the Variableargumentmethod function body traverses the parameters passed in the variable parameter table and outputs it with printf ("%d,", Va_arg (parg, int)).

II. details of implementation

1. Find out how the compiler handles the problem of passing parameters.

The compiler pushes the parameters into the stack for delivery. When the argument is passed, the compiler will be in the argument list, from right to left in the order of the parameters into the stack, for Variableargumentmethod (6, 4, 7, 3, 0, 7, 9) calls, then the order into the stack is 9, 7, 0, 3, 7, 4, 6 (note that there is no variable parameters and cannot Variable parameter). Since the address of the stack is from high to low, the actual parameter is distributed as shown in the stack after the argument is placed in the stack. As you can see, the argument is in the stack, or the left parameter is at a low address, and the right parameter is in a high address state. OK, that's enough to know.

Low address High address

...

6

4

7

3

0

7

9

...

Stack

2. Va_list, Va_start, Va_arg and Va_end

Va_list is a defined pointer type, Va_start, Va_arg, and va_end are all macros defined by the C language for handling variable parameters, in the Stdarg.h file. Because of the different hardware platform, the compiler is different, resulting in their definitions are different, but the basic idea is the same. The following is the definition of the related macro.

Copy Code code as follows:

typedef char * VA_LIST;

#define _ADDRESSOF (V) (& (v))

#define _INTSIZEOF (N) (sizeof (n) + sizeof (int)-1) & ~ (sizeof (int)-1))

#define VA_START (AP,V) (AP = (va_list) _addressof (v) + _intsizeof (v))

#define VA_ARG (Ap,t) (* (t *) (AP + _intsizeof (t))-_intsizeof (t))

#define VA_END (AP) (AP = (va_list) 0)

As you can see, two other macros _addressof and _intsizeof are introduced here.

_addressof (v) is used to get the variable address, which can be seen at a glance;

_intsizeof (n) is used for alignment. (What is alignment?) This is due to the structure of the stack, in 32-bit machines, each cell in the stack is 4 bytes, which is often the length of an int, but the actual parameters may not be exactly 4 bytes, or just 4 times the number of bytes, as if the car would not sell half a seat to the passengers, If the incoming data does not exactly account for 4 or 4 times the number of bytes, you need to align (padded). As to why this expression can be aligned, need to analyze it;

In Va_start (AP,V), the AP is a pointer for holding a variable parameter, and V is the last variable parameter, (va_list) _addressof (v) Gets the address of V and converts to the va_list type, and V is the parameter of the last variable parameter, in this case 6, the low address end of the stack in the above figure, _intsizeof (v) Gets an alignment address, where 4, two are added, which points to the first variable parameter, 4 in the previous figure, and assigns that value to the AP, and then the AP points to the first variable parameter. (It can be seen from here that it is useful to define va_list as char*, because char length is one byte and is convenient for pointer operation);

Va_arg (AP,T), the AP is a pointer for holding a variable parameter, T is the type to get the parameter, AP + + _intsizeof (t) has the AP = the next parameter, but the value of the current parameter needs to be fetched, so that the expression is returned as a va_list (char*) Type of pointer, so to transition to t* after the dereference operation, get the value of the current parameter. (Note that there is an operation to move the AP down one parameter and back. I'm not feeling well, on the one hand there is a wasteful operation that has some effect on performance, on the other hand, I would prefer to detach the operation from the current value and move to the next one, so that the programmer can have more control and be easy to understand. )

Va_end (AP) is to have the AP point to an empty address.

Through the above analysis, you can find that the C language variable parameters are accessed sequentially from the stack, the process used in the three macros, but also simple operation of the packaging, can be programmed to achieve their own. Moreover, the type and number of parameters cannot be directly determined, in this case, the first parameter of the Variableargumentmethod is used to specify the number of parameters, and the type of the argument is fixed so that the program can function correctly, and then printf, it can recognize the number of parameters, It is because the first argument must describe the format string for the following argument, which is the problem to be noted in the first question mentioned at the outset. That's why it's been criticized by a lot of people, but I think it's a good way to compare it to the way Java and. NET are implemented.

The way Java and. NET implement variable parameters.

Java supports variable parameters since 1.5, and its definition syntax is:

Copy Code code as follows:

void TestMethod (String ... args)

For this method, this can be called: TestMethod ("gly", "Zxy", "Chenfei");

. NET also supports variable parameters whose definition syntax is:

Copy Code code as follows:

void TestMethod (params string[] args)

For this method, this can be called: TestMethod ("gly", "Zxy", "Chenfei");

In Java and. NET, implementations of variable parameters are essentially the same: at compile time, the compiler treats the variable parameters in the method signature as an array of the appropriate type, compiles the corresponding call, generates an array from the arguments, loads the parameters into the array, and in the method body of the variable parameter method, Use variable parameters in the same way that arrays are used.

The comparison of two ways of realization

C language Implementation and Java. NET's implementation, C language requires programmers to do more work, and, indeed, increased the chance of error, java. NET implementation can easily determine the type and number of parameters, these C implementation is not, but Java. NET implementation side Type generates a temporary array, of course, Java. NET has a garbage collection mechanism, but when garbage is recycled is uncertain, and is very expensive, garbage collection is a good thing, but I do not like, I think the unwanted things should be released immediately, this is the embodiment of a perfect aspect. There is no such problem in C, the number and type of parameters can be solved by convention or designation, and in both Java and. NET, the number of parameters is passed indirectly (the length of the array), and the parameter type is agreed in the method signature. Of course, Java. NET design goals and C language is different, there are many.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.