Implementation of variable parameters in C ++

Source: Internet
Author: User

The implementation of variable parameters solves three problems:

1. How to call a function with variable parameters
2. Compile a program with variable parameters
3. How to hold variable parameters in a function body with variable parameters
The first problem is that you can pass in variable parameters when calling. Of course, there are some notes that will be mentioned later.

The second problem is that the compiler needs to adopt a loose check scheme during compilation, which will bring some problems, such as unfavorable programming error checking.

The third is my concerns here. I will take the C language as an example to analyze its implementation principles.

Printf and scanf are the most common variable parameter functions in the C language standard library. The printf signature is

Copy codeThe Code is as follows: int printf (const char * format ,...);

Here,... represents a variable parameter, and now a simple example is written to imitate printf.

I. A simple example:

Copy codeThe Code is 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 ,...){
// Declare a pointer to hold variable parameters
Va_list pArg;
// Initialize pArg to point to the first parameter
Va_start (pArg, argc );
// Output parameters
For (int I = 0; I! = Argc; ++ I ){
// Obtain and output the parameters that pArg points
Printf ("% d,", va_arg (pArg, int ));
}

Va_end (pArg );
}

Void VariableArgumentMethod (int argc,...) is a variable parameter function used to output variable parameters of a specified number of argc.
VariableArgumentMethod (6, 4, 7, 3, 0, 7, 9); is used to call this function. The first real parameter 6 indicates that six parameters are followed.

In the function body of VariableArgumentMethod:

1. va_list pArg;

Defines a pointer to hold a variable parameter. by moving the pointer in the input variable parameter table, you can hold the first variable parameter.

2. va_start (pArg, argc );

Point pArg to the first parameter in the Variable Parameter List. Argc is a parameter for positioning, because variable parameters start after argc and will explain why this is the case.

3. va_arg (pArg, int );

This statement is placed in the loop body to retrieve the parameters in the variable parameter table. In addition, it moves the pArg to the next variable parameter (if it has reached the end, it will point to a meaningless address ).

4. va_end (pArg );

To clear the pArg, I personally think it is dispensable here, because pArg is no longer needed.

In this way, the VariableArgumentMethod function traverses the parameters passed in the variable parameter table and outputs the data using printf ("% d,", va_arg (pArg, int.

II. Implementation Details

1. First, let's take a look at how the compiler handles the problem of passing parameters.

The compiler pushes parameters to the stack for transfer. When passing real parameters, the compiler will import the parameters into the stack from the real parameter list in the order from right to left. For VariableArgumentMethod (6, 4, 7, 3, 0, 7, 9) call, the order of the incoming stack is 9, 7, 0, 3, 7, 4, 6 (note that there is no variable parameter or immutable parameter ). Since the stack address is from high to low, the distribution of real parameters in the stack is as follows after the real parameters are added to the stack. It can be seen that in the stack, the parameters on the left remain in the low address and parameters on the right are in the high address State. OK. knowing this is enough.

Low address and 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. Both va_start, va_arg, and va_end are macros defined by the C language for processing variable parameters. In the stdarg. h file. Due to the differences in the hardware platform and compiler, their definitions are also different, but the basic idea is the same. The following are macro definitions.

Copy codeThe Code is 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)

We can see that two other macros _ ADDRESSOF and _ INTSIZEOF are introduced here.

_ ADDRESSOF (v) is used to obtain the variable address, which can be seen at a glance;

_ INTSIZEOF (n) is used for alignment. (What is alignment? This is caused by the stack structure. In 32-bit machines, each unit in the stack occupies 4 bytes, which is usually an int-type length, however, the actually passed parameters may not be exactly four bytes, or exactly a multiple of four bytes, as if they would not sell half a seat to a passenger during a ride, if the input data does not exactly count as 4 or a multiple of 4 bytes, You need to align (complete ). As to why this expression can be aligned, we need to analyze it );

In va_start (ap, v), ap is the pointer used to hold the variable parameter, v is the last non-variable parameter, (va_list) _ ADDRESSOF (v) gets the v address, and convert it to the va_list type. v is the parameter of the last Non-variable parameter. In this example, it should be 6. At the low address end of the Processing Stack, _ INTSIZEOF (v) an alignment address is obtained. Here it should be 4. After the two are added, it points to the first variable parameter, that is, 4 in. After this value is assigned to the ap, let the ap point to the first variable parameter. (It can be seen from this that it is very useful to define va_list as char *, because the char length is one byte, which facilitates pointer operation );

In va_arg (ap, t), ap is a pointer to a variable parameter, t is the type of the parameter to be obtained, ap + = _ INTSIZEOF (t) points the ap to the next parameter, however, the value of the current parameter needs to be obtained here, so the expression is reduced and a va_list (char *) pointer is returned, therefore, we need to convert it to t * And then perform the dereference operation to obtain the value of the current parameter. (Note that here is an operation that removes the ap from the next parameter. I don't feel very good. On the one hand, there is a waste of operations, which may affect the performance. On the other hand, I want to separate the operations that take the current value from the operations that move to the next one. This gives programmers more control and is easy to understand .)

Va_end (ap) enables the ap to point to an empty address.

Through the above analysis, we can find that variable parameters in C are accessed sequentially from the stack. The three macros used in the process are only simple packaging of operations, it can be programmed by yourself. In this example, the first parameter of VariableArgumentMethod is used to specify the number of parameters. The parameter type Convention is an integer, in this way, the program can run normally. In printf, the number of parameters can be identified because the format string of the following parameter must be described in the first parameter, this is the first issue mentioned at the beginning. This is also why it has been criticized by many people. However, I think this method is good and will be compared with java and. net implementations later.

3. Implement variable parameters in java and. net.

After java 1.5, variable parameters are supported. The syntax is as follows:

Copy codeThe Code is as follows: void testMethod (String... args)

For this method, you can call: testMethod ("ugly", "zxy", "ChenFei ");

. Net also supports variable parameters. Its definition syntax is:

Copy codeThe Code is as follows: void TestMethod (params string [] args)

For this method, you can call: TestMethod ("ugly", "zxy", "ChenFei ");

In java and. net, the implementation of variable parameters is basically the same: When the compiler is compiling, the variable parameters in the method signature are considered as corresponding types of arrays. when compiling the corresponding calls, an array is generated based on the real parameters, and the parameters are loaded into the array for transmission. In the method body of the Variable Parameter Method, variable parameters are used as arrays.

Iv. Comparison of the two implementation methods

The implementation of C and java. compared with the net implementation method, the C language requires programmers to do more work, and it does increase the chance of errors, java. net implementation method can easily determine the parameter type and number, these C implementations are not, but java. net will generate a temporary array, of course, java. net has a garbage collection mechanism. However, it is uncertain when garbage is recycled, and it is costly. Garbage collection is a good thing, but I don't like it, I think that something that is not needed should be released immediately, which is a perfect embodiment. C does not have this problem. The number and type of parameters can be solved by conventions or designation. in 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, the design goal of java. net is different from that of C.

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.