Another implementation of variable parameters in C ++

Source: Internet
Author: User

The well-known C-library function printf is a variable parameter function. How does it implement it? However, its implementation is conditional, and the function parameter's inbound stack order must be the order from right to left, that is, the function parameter. Before the function is called, it must be the rightmost parameter that is first imported into the stack, and the parameters must be passed through the stack. The following example shows the function func (arg1, arg2, arg3 ), the function stack should be:

EBP is a frame pointer register, which is generally used to access the stack. With the stack structure, let's take a look at the specific implementation principles of variable C parameters:

# Include <stdio. h> Enum {ptchar, ptint, ptfloat, ptdouble,}; void printsum (unsigned long paramformat ,...) {/* The 16-bit high is the variable parameter type, and the 16-bit low is the variable parameter count */INT paramtype = (paramformat> 16); int paramnum = paramformat & 0 xFFFF; /* required mformat = EBP + 8, address of the first parameter */unsigned long * parg = required mformat;/* EBP + 0x0c, address of the second parameter */parg ++; switch (paramtype) {Case ptchar: {int sum = 0; For (INT I = 0; I <paramnum; I ++) {char * pvalue = (char *) parg; su M + = * pvalue; parg ++;} printf ("% d \ n", sum);} break; Case ptint: {int sum = 0; for (INT I = 0; I <paramnum; I ++) {int * pvalue = (int *) parg; sum + = * pvalue; parg ++ ;} printf ("% d \ n", sum) ;}break; Case ptfloat: {float sum = 0;/**/parg ++;/* floating point parameter, the stack occupies 8 bytes, so the pointer offset is 8 */For (INT I = 0; I <paramnum; I ++) {float * pvalue = (float *) parg; sum + = * pvalue; parg ++;} printf ("% F \ n", sum) ;} break; Case ptdouble: {double sum = 0 ;/ * Double-precision floating-point parameters, the stack occupies 8 bytes, so the pointer offset is 8 */For (INT I = 0; I <paramnum; I ++) {double * pvalue = (double *) parg; sum + = * pvalue; parg ++;} printf ("% F \ n", sum );} break; default: printf ("unknowned type! \ N "); break ;}} void main () {unsigned long paramformat = 3; char a = 1, B = 2, c = 3; printsum (paramformat,, b, c); paramformat = ptint <16; paramformat + = 3; int IA = 1, IB = 2, Ic = 3; printsum (paramformat, IA, IB, ic); paramformat = ptfloat <16; paramformat + = 3; float fa = 1, Fb = 2, Fc = 3; printsum (paramformat, fa, FB, FC ); paramformat = ptdouble <16; paramformat + = 3; double da = 1, DB = 2, Dc = 3; printsum (paramformat, da, DB, DC );}

the method above imposes restrictions on the order of function parameters in the stack. The method must be right-to-left, which is why Pascal's call method cannot implement printf, in addition, function parameters must be passed through the stack. For Some compilers to optimize the processing, function parameters are passed through registers, which does not meet the requirements. For this reason, this article uses the C ++ default parameter to implement variable parameters. Without these restrictions, the following is the implementation of Code :

# Include <stdio. h> Enum {ptchar, ptint, ptfloat, ptdouble,}; void printsum (unsigned long paramtype, void * arg1 = null, void * arg2 = null, void * arg3 = NULL, void * arg4 = null, void * arg5 = null, void * arg6 = null, void * arg7 = null, void * Arg8 = null, void * arg9 = NULL, void * arg10 = NULL) {void * Arg [10] = {arg1, arg2, arg3, arg4, arg5, arg6, arg7, Arg8, arg9, arg10 ,}; switch (paramtype) {Case ptchar: {int sum = 0; fo R (INT I = 0; I <10; I ++) {If (ARG [I]! = NULL) {char * pvalue = (char *) Arg [I]; sum + = * pvalue;} elsebreak;} printf ("% d \ n", sum );} break; Case ptint: {int sum = 0; For (INT I = 0; I <10; I ++) {If (ARG [I]! = NULL) {int * pvalue = (int *) Arg [I]; sum + = * pvalue;} elsebreak;} printf ("% d \ n", sum );} break; Case ptfloat: {float sum = 0; For (INT I = 0; I <10; I ++) {If (ARG [I]! = NULL) {float * pvalue = (float *) Arg [I]; sum + = * pvalue;} elsebreak;} printf ("% F \ n", sum );} break; Case ptdouble: {double sum = 0; For (INT I = 0; I <10; I ++) {If (ARG [I]! = NULL) {double * pvalue = (double *) Arg [I]; sum + = * pvalue;} elsebreak;} printf ("% F \ n", sum );} break; default: printf ("unknowned type! \ N "); break ;}} void main () {unsigned long paramtype = ptchar; char a = 1, B = 2, c = 3; printsum (paramtype, &, & B, & C); paramtype = ptint; int IA = 1, IB = 2, Ic = 3; printsum (paramtype, & IA, & IB, & ic ); paramtype = ptfloat; float fa = 1, Fb = 2, Fc = 3; printsum (paramtype, & FA, & FB, & FC); paramtype = ptdouble; double da = 1, DB = 2, Dc = 3; printsum (paramtype, & Da, & dB, & DC );}

 

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.