[C/C ++] variable parameter table (Variable Arguments)

Source: Internet
Author: User
Tags addall

 

C/C ++ supports variable-length function parameter tables. programmers can obtain arbitrary function parameters through pointer operations.
The default _ cedcl call specification for C/C ++ stipulates that:
The pressure stack and pop-up operations of function parameters are performed by the main caller. Therefore, the called function does not need to know the number of parameters. To use this variable parameter function call, you must add the ellipsis "..." formed by three periods at the end of the parameter table.

Void g (int A, char * C ,...);

The comma before the ellipsis is optional and does not affect lexical syntax analysis. The above function g can accept two or more parameters. The type of the first two parameters is fixed, the subsequent parameter type is unknown, and the number of parameters is unknown. To know the number of parameters, we must use other methods, such as passing through the first parameter:

G (3, "Hello", 2, 4, 5); // call G and pass 5 parameters. The last 3 are variable parameters.

In the implementation code of the function, you can access the parameters in the variable parameter table by sorting the parameters in the stack. For example:

Void g (int A, char * C ...)

{

Void * Pc = & C; int * Pi = static_cast <int *> (PC) + 1; // point pi to the first Variable Parameter

For (INT I = 0; I <A; I ++) STD: cout <PI [I] <"";

STD: cout <C <STD: Endl;

}

We can even make all parameters of a function variable, as long as there is a way to know the number of parameters. For example, we agree that all parameters passed to addall are int and the last one ends with 0:

Int addall (...);

Int A = f );

Addall can be implemented as follows:

Int addall (...){

Int sum = 0; int * P = & sum; // P points to the first local variable

P + = 3; // skip sum, EBP, and EIP. Now P points to the first parameter.

For (; * P; ++ p) // continues the loop if p does not point to 0

Sum + = * P;

Return sum;

}

The most widely used Variable Parameter tables are formatted input and output in C's standard library functions: printf and scanf.

Void printf (char * C ,...);

Void scanf (char * C ,...);

Both of them use its first parameter to indicate the type and quantity of parameters in the subsequent parameter table.

If the types of parameters in a variable parameter table are different, complicated pointer operations are required to manipulate the variable parameter table, and align is a headache. Fortunately, the c Standard Library provides macros (macro) and structures (struct) used to manipulate Variable Parameter tables, which are defined in the library file stdarg. h:

Typedef struct {char * P; int offset;} va_list;

# Define va_start (valist, ARG)

# Define va_arg (valist, type)

# Define va_end (valist)

The structure va_list is used to indicate the position of the parameter in the stack. The macro va_start accepts the parameters before the variable parameter table of a va_list and function, and initializes the corresponding data in va_list through the first parameter. Therefore, stdarg is used. h macro. Your variable parameter table function must have at least one named parameter. Va_arg returns the next type parameter. va_end ends the variable parameter table. Here, we use addall as an example to write the standard macro version:

Int addall (int I ,...)

{

Va_list VL; // defines a va_list structure.

Va_start (VL, I); // use the parameter before the ellipsis to initialize VL

If (I = 0) return 0; // if the first parameter is 0, return

Int sum = I; // Add the first parameter to sum

For (;;){

I = va_arg (VL, INT); // obtain the next parameter, type: Sum

If (I = 0) break; // If the parameter is 0, the loop jumps out.

Sum + = I;

}

Va_end (VL );

Return sum;

}

It can be seen that if the parameter types are consistent, more lines of code are required to use the standard library. However, if the parameter types are inconsistent or unknown (in the case of printf), it is much easier to use the standard library, because it is difficult to guess the details of the compiler processing the Assembly Code such as boundary align. Code from the standard library can be transplanted, and variable parameter table manipulation using other methods described above is not portable, and is only available on the i386 platform.

Even if a variable parameter table is easy to use, it has many defects. Portability and platform dependency are only one of them. The biggest problem is its type insecurity. Using a variable parameter table means that the compiler does not perform any type check on the parameters. This is a tough historical issue in C. In C ++, it means that the demon reinterpret_cast is awakened by you. The variable parameter table of C is one of the root causes of frequent errors in the C ++ code, so that the variable parameter table of C ++ is listed as the legacy feature of C language that will be abolished. Many new features in the C ++ syntax, such as overload functions, default parameter values, and templates, can replace Variable Parameter tables to a certain extent, and are more secure than variable parameter tables.

Variable parameter table is the only award-worthy contribution in C ++. It is the worst matching overload that can be created by using variable parameter table in the template meta programming (TMP) sfinae technology. According to the rules related to function overload resolution in the C ++ standard, functions with Variable Parameter tables always have the worst match, and the compiler selects the variable parameter table only when the compiler is forced to leave nowhere. With this, we can carefully create overload functions to extract type information. For example, to determine whether a type passed through the template is int:

Long isinibd (INT );

Char isinibd (...);

Template <typename T>

Struct isint

{

Enum {value = sizeof (isinibd (T () = sizeof (long );}

}

Then, in a function with template parameter T, we can write

If (isint <t>: Value )//...

In this (not refined) example, if T is int, the first overload version of isinibd will be selected, and the return value type is long, so the value is 1. Otherwise, the compiler can only select the second overloaded version with a variable parameter table. The return value type is Char, so that the value is 0. I can understand it more clearly. The code above indicates that if the type T is int, It is int. Otherwise, it is not int. This method extracts type information by reloading resolution rules, which is called sfinae in template meta-programming, it is widely used in the development and implementation of STL, boost, and other template libraries.

It is worth noting that in the above sfinae application, isinibd does not have definitions but only provides declarations, because we have not actually called the isinibd function, instead, let it participate in the overload resolution and use sizeof to determine its return value type. This is the perfect embodiment of a design criterion of C ++: things that are not needed can not appear. This principle avoids the dangerous action of calling a function with a variable parameter table in C ++. Instead, it only uses the special position of a variable parameter table in the syntax analysis process, this clever use of dangerous language features is good and harmless.

 

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.